Skip to content

网络编程

网络协议

TCP(传输控制协议)和UDP(用户数据报协议)是互联网中两种核心的 传输层协议,用于在设备间传输数据。

TCP

特点:

  • 面向连接:通信前需要通过三次握手建立连接,结束后通过四次挥手断开;
  • 可靠传输:通过确认应答、重传机制、数据排序等确保数据完整有序到达;
  • 顺序控制:它会保证数据包按顺序到达,接收方会根据序列号进行排序;
  • 流量控制和拥塞控制:TCP具有流量控制和拥塞控制功能,以防止网络堵塞;

适用场景:

  • 对可靠性要求高的应用,如网页浏览、文件传输、邮件服务。

三次握手

三次握手是客户端与服务器建立连接的过程,它保证了通信双方建立一个可靠的连接。

  • 第一次握手:客户端向服务器发送一个 SYN 包,其中包含客户端的初始序列号,表示请求建立连接;
  • 第二次握手:服务器收到 SYN 包后,会向客户端发送一个 SYN/ACK 包,其中包含服务器的初始序列号和对客户端序列号的确认;
  • 第三次握手:客户端收到 SYD/ACK 包后,会向服务器发送一个 ACK 包,其中包含对服务器序列号的确认;

四次挥手

四次挥手用于在客户端和服务器之间断开一个连接。

  • 第一次挥手:客户端向服务器发送一个 FIN 包,表示客户端已经没有数据要发送了;
  • 第二次挥手:服务器收到 FIN 包后,会向客户端发送一个 ACK 包,表示服务器已经收到了客户端的 FIN 包;
  • 第三次挥手:服务器向客户端发送一个 FIN 包,表示服务器已经没有数据要发送了;
  • 第四次挥手:客户端收到 FIN 包后,会向服务器发送一个 ACK 包,表示客户端已经收到了服务器的 FIN 包;

UDP

特点:

  • 无连接:UDP是一种无连接的协议,发送数据之前不需要建立连接,数据包独立传输;
  • 不可靠:UDP不保证数据包的到达,也不保证顺序,丢失都得数据包不会重新传输;
  • 传输效率高:因为没有建立连接和维护状态,它比TCP更轻量,传输效率较高;

适用场景:

  • 适用于对实时性要求高,容忍丢包的应用,如视频流、在线游戏、语音通话等;

TCP使用

服务端

java
public static void main(String[] args) throws IOException {
  System.out.println("服务端已启动,等待客户端连接...");

  // 创建 ServerSocket 对象,并指定端口
  ServerSocket serverSocket = new ServerSocket(6666);
  // 服务端等待客户端连接(这里会阻塞程序)
  Socket accept = serverSocket.accept();

  // 读取客户端发送过来的数据
  InputStream inputStream = accept.getInputStream();
  byte[] bytes = new byte[1024];
  int len = inputStream.read(bytes);
  System.out.println("收到客户端消息:" + new String(bytes, 0, len));

  // 向客户端回复数据
  OutputStream outputStream = accept.getOutputStream();
  outputStream.write("给你10个大电影,注意身体!".getBytes());

  // 释放资源
  serverSocket.close();
  accept.close();
  inputStream.close();
  outputStream.close();
}

客户端

java
public static void main(String[] args) throws IOException {
  // 创建 socket 对象,指定IP和端口号
  Socket socket = new Socket("127.0.0.1", 6666);

  // 向服务端发送数据
  OutputStream outputStream = socket.getOutputStream();
  outputStream.write("我想下载两个小电影".getBytes());

  // 接收服务端回复的数据
  InputStream inputStream = socket.getInputStream();
  byte[] bytes = new byte[1024];
  int len = inputStream.read(bytes);
  System.out.println(new String(bytes, 0, len));

  // 释放资源
  socket.close();
  outputStream.close();
  inputStream.close();
}

UDP使用

服务端

java
public static void main(String[] args) throws IOException {
  System.out.println("UDP服务端已启动,等待客户端发送消息...");

  // 创建UDP socket,监听端口为 6666
  DatagramSocket socket = new DatagramSocket(6666);

  // 接收客户端数据
  byte[] bytes = new byte[1024];
  DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
  socket.receive(packet);

  // 解析数据
  byte[] data = packet.getData();
  int length = packet.getLength();
  System.out.println("收到服务端消息:" + new String(data, 0, length));

  InetAddress address = packet.getAddress();
  int port = packet.getPort();
  System.out.println("IP:" + address + ":" + port);

  // 释放资源
  socket.close();
}

客户端

java
public static void main(String[] args) throws IOException {
  // 创建 DatagramSocket 对象
  DatagramSocket socket = new DatagramSocket();

  // 创建 DatagramPacket 对象,将数据进行打包
  byte[] bytes = "你好啊".getBytes();
  InetAddress ip = InetAddress.getByName("127.0.0.1");
  int port = 6666;
  DatagramPacket packet = new DatagramPacket(bytes, bytes.length, ip, port);

  // 发送数据
  socket.send(packet);
  // 释放资源
  socket.close();
}
java
public static void main(String[] args) throws IOException {
  // 创建 DatagramSocket 对象
  DatagramSocket socket = new DatagramSocket();

  // 创建 DatagramPacket 对象,将数据进行打包
  byte[] bytes = "你好啊".getBytes();
  InetAddress ip = InetAddress.getByName("127.0.0.1");
  int port = 6666;
  DatagramPacket packet = new DatagramPacket(bytes, bytes.length, ip, port);

  // 发送数据
  socket.send(packet);
  // 释放资源
  socket.close();
}

Released under the MIT License.