为热爱编程的你点赞!
学习SpringBoot实战课程 https://edu.csdn.net/course/detail/31433
学习SpringCloud入门课程 https://edu.csdn.net/course/detail/31451
本文带大家了解TCP协议概念,实现Socket的基本通信,文件上传,最后会用Socket实现模拟的服务器。
TCP(Transmission Control Protocol)传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP协议的特点:
TCP协议的可靠性主要基于三次握手和四次挥手机制
三次握手:
简单来说:类似某男追某女
简单来说:类似某男和某女分手
TCP和UDP同属于传输层协议,对比TCP和UDP:
UDP | TCP | |
---|---|---|
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输 | 可靠传输 |
连接个数 | 支持一对一,一对多,多对多通信 | 只能是一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
适用场景 | 适用于实时应用(IP电话、视频会议、直播等) | 适用于要求可靠传输的应用,例如文件传输 |
Socket基于TCP/IP协议,用于客户端和服务器端通信。
网络套接字,用于连接另一台计算机
创建方法:
new Socket("IP地址",端口号)
注意:一旦创建了Socket对象,就自动连接对方计算机
常用方法:
注意:一旦输入流或输出流关闭,Socket连接会自动关闭。
服务器端Socket,Socket的子类,用于接受客户端并和客户端通信
创建:
new ServerSocket(端口号)
注意:一旦创建ServerSocket对象,会不断侦听该端口,判断是否有客户端连接
主要方法:
服务器端实现步骤:
public class Server {
public static final int PORT = 8888;
public void start(){
System.out.println("启动服务器。。。");
//创建ServerSocket对象
try {
ServerSocket server = new ServerSocket(PORT);
//循环获得客户端连接
while(true){
Socket client = server.accept();
System.out.println(client.getInetAddress()+"连接了");
//获得客户端的输入流和输出流
try(DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream())){
//读取客户端的消息
System.out.println("客户端"+client.getInetAddress()+"说:"+dis.readUTF());
//给客户端发消息
dos.writeUTF("我是服务器端,客户端你好啊~~~~~~~~~~~~~~~~");
}catch(IOException ex){
ex.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Server().start();
}
}
客户端实现步骤:
public class Client {
public void sendMessage(String ip,int port,String msg){
//创建Socket对象,连接服务器端
try {
Socket socket = new Socket(ip,port);
//获得输出流和输入流
try(DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(socket.getInputStream())){
//发送数据给服务器端
dos.writeUTF(msg);
//读取服务器端的消息
System.out.println("服务器端说:"+dis.readUTF());
}catch(Exception ex){
ex.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client().sendMessage("192.168.53.5", 8888,
"你好!!!服务器端");
}
}
文件的上传的步骤
服务器端:
客户端:
public class FileServer {
public static final int PORT = 8888;
public static final String DIR = "C:\\upload\\";
public void start(){
System.out.println("start...");
//创建服务器端对象
try (ServerSocket server = new ServerSocket(PORT);){
//调用accept接受客户端连接
while(true){
Socket socket = server.accept();
//创建文件输出流和网络输入流
try(ObjectInputStream in = new ObjectInputStream(
socket.getInputStream());
//读取客户端发来的文件名,创建文件输出流
OutputStream out =
new FileOutputStream(DIR+in.readUTF());){
//从网络中读取数据,写入到本地磁盘
int len = 0;
byte[] buffer = new byte[1024];
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}
System.out.println("服务器保存完毕");
}catch(IOException ex){
ex.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new FileServer().start();
}
}
public class FileClient {
/**
* 发送文件
*/
public void sendFile(String ip,int port,String path){
File file = new File(path);
//创建连接,创建文件输入流,网络输出流
try(Socket socket = new Socket(ip,port);
InputStream in = new FileInputStream(path);
ObjectOutputStream out = new ObjectOutputStream(
socket.getOutputStream())){
//先发送文件名给服务器
out.writeUTF(file.getName());
out.flush();
//读取本地文件数据,写入到网络输出流中
int len = 0;
byte[] buffer = new byte[1024];
while((len = in.read(buffer)) != -1){
out.write(buffer, 0, len);
}
System.out.println("客户端发送完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new FileClient().sendFile("127.0.0.1", 8888,
"D:\\java_code\\Test10.java");
}
}
HTML服务器的简单工作原理:
/**
* 模拟服务器
*/
public class MyTomcat {
private static final int PORT = 8888;
private static final String WEB_DIR = "D:/webapps";
public void start(){
//创建服务端Socket
try(ServerSocket server = new ServerSocket(PORT)){
System.out.println("服务器启动了。。。。");
while(true){
//接受客户端连接
Socket client = server.accept();
//读取浏览器的请求
service(client);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//服务客户端
public void service(Socket client){
//获得客户端的输入流和输出流
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(client.getInputStream()));
BufferedOutputStream writer = new BufferedOutputStream(
client.getOutputStream())){
//读取客户端的请求信息
String request = reader.readLine();
if(request == null){
return;
}
System.out.println(request);
//将请求进行分割
String[] requests = request.split("\\ ");
if(requests.length < 2){
return;
}
//通过请求头中的路径查找文件
String path = requests[1];
File file = new File(WEB_DIR+path);
if(!file.exists()){
//如果不存在,就发送404错误
writer.write("HTTP/1.1 404 NOT FOUND\r\n".getBytes());
}else{
//如果存在,就发送200
writer.write("HTTP/1.1 200 OK\r\n".getBytes());
//读取本地HTML文件的内容
BufferedReader br = new BufferedReader(new FileReader(file));
StringBuilder strb = new StringBuilder();
String line = null;
while((line = br.readLine()) != null){
strb.append(line);
}
br.close();
String html = strb.toString();
System.out.println("html-->"+html);
//发送响应头给客户端
String header = "Content-Type:text/html;charset=utf-8\r\n"
+ "Content-Length:"+html.getBytes("UTF-8").length+"\r\n";
writer.write(header.getBytes());
//正文和响应头之间发送分割符号
writer.write(new byte[]{10,13},0,2);
//发送正文
writer.write(html.getBytes("UTF-8"));
System.out.println("发送完毕!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyTomcat myTomcat = new MyTomcat();
myTomcat.start();
}
}
在D:/webapps下添加hello.html文件,启动服务器
在浏览器输入测试:http://localhost:8888/hello.html
大家如果需要学习其他Java知识点,戳这里 超详细的Java知识点汇总