本文深入讲解Java网络编程中的TCP和UDP的使用,并且探究网络连接中三次挥手与四次挥手的详细步骤。
一、TCP
TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议。通过三次握手建立连接,确保数据的可靠传输。TCP 具有流量控制、拥塞控制和重传机制,能够保证数据按序到达,不会丢失或重复。TCP 适合用于对数据准确性要求较高的应用场景,如文件传输、电子邮件、电商订单支付状态同步等。
服务端TCPServer代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("服务器已启动,等待客户端连接...");
while (true) {
// 阻塞等待客户端连接
Socket clientSocket = serverSocket.accept();
System.out.println("客户端已连接:" + clientSocket.getInetAddress());
// 读取客户端发送的数据
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
String message = in.readLine();
System.out.println("收到客户端消息:" + message);
// 向客户端发送响应
java.io.PrintWriter out = new java.io.PrintWriter(clientSocket.getOutputStream(), true);
out.println("服务器已收到消息:" + message);
}
// 关闭客户端连接
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端TCPClient代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
// 向服务器发送消息
String message = "Hello, Server!";
out.println(message);
System.out.println("已发送消息:" + message);
// 接收服务器响应
String response = in.readLine();
System.out.println("收到服务器响应:" + response);
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、三次握手(建立连接)
三次握手是 TCP 协议用于建立连接的过程,目的是确保双方都具有接收和发送数据的能力,并且协商初始序列号。具体步骤如下:
第一次握手:
- 客户端向服务器发送一个 SYN包,其中包含客户端的初始序列号。这个包表示客户端请求建立连接。客户端进入 SYN_SENT 状态。
第二次握手:
- 服务器收到客户端的 SYN 包后,向客户端发送一个 SYN + ACK 包。SYN 包包含服务器的初始序列号,ACK(确认号)包用于确认客户端的 SYN 包,确认号为客户端的初始序列号加 1。服务器进入 SYN_RECV 状态。
第三次握手:
- 客户端收到服务器的 SYN + ACK 包后,向服务器发送一个 ACK 包,确认号为服务器的初始序列号加 1。客户端和服务器都进入 ESTABLISHED 状态,连接建立成功。
三次握手的主要作用是确保双方都知道彼此已经准备好进行数据传输,避免了因网络延迟或其他问题导致的错误连接。
三、四次挥手(断开连接)
四次挥手是 TCP 协议用于断开连接的过程,确保双方都能正确地关闭连接,释放资源。具体步骤如下:
第一次挥手:
- 客户端向服务器发送一个 FIN(结束)包,表示客户端不再发送数据,但仍可以接收数据。客户端进入 FIN_WAIT_1 状态。
第二次挥手:
- 服务器收到客户端的 FIN 包后,向客户端发送一个 ACK 包,确认号为客户端的序列号加 1。服务器进入 CLOSE_WAIT 状态,客户端进入 FIN_WAIT_2 状态。此时,客户端到服务器的连接已经关闭,但服务器到客户端的连接仍然可以继续传输数据。
第三次挥手:
- 当服务器没有数据要发送时,向客户端发送一个 FIN 包,表示服务器也不再发送数据。服务器进入 LAST_ACK 状态。
第四次挥手:
- 客户端收到服务器的 FIN 包后,向服务器发送一个 ACK 包,确认号为服务器的序列号加 1。客户端进入 TIME_WAIT 状态,经过一段时间2MSL后,客户端关闭连接。服务器收到客户端的 ACK 包后,立即关闭连接。
四次挥手的主要原因是 TCP 连接是全双工的,每个方向的连接都需要单独关闭,因此需要四次交互来确保双方都能正确地关闭连接。
四、 UDP
UDP 是一种无连接的、不可靠的传输层通信协议。不保证数据的可靠传输,也不保证数据的顺序到达。UDP 没有建立连接的过程,因此具有较低的开销和较高的传输效率,适用于对实时性要求较高、允许少量数据丢失的应用场景,如实时视频、音频传输、游戏、商品库存实时广播等。
发送端UDPSender:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSender {
public static void main(String[] args) {
try (DatagramSocket socket = new DatagramSocket()) {
// 要发送的数据
String message = "Hello";
byte[] buffer = message.getBytes();
// 目标地址和端口
InetAddress address = InetAddress.getByName("localhost");
int port = 8888;
// 创建 DatagramPacket 对象
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, port);
// 发送数据包
socket.send(packet);
System.out.println("已发送消息:" + message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
接收端UDPReceiver:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceiver {
public static void main(String[] args) {
try (DatagramSocket socket = new DatagramSocket(8888)) {
// 创建缓冲区
byte[] buffer = new byte[1024];
// 创建 DatagramPacket 对象用于接收数据
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 接收数据包
socket.receive(packet);
// 处理接收到的数据
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到消息:" + message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
← 上一篇 Java进阶——常用工具类 |
记得点赞、关注、收藏哦!
| 下一篇 Java进阶——IO流实战详解 → |