TCP 三次握手后的消息交换过程
当 TCP 完成三次握手建立连接后,客户端和服务端就可以开始双向传输数据。以下是一个典型的数据交换流程示例:
完整交互流程
1. 三次握手建立连接
客户端 -----[SYN: Seq=x]-----> 服务端
客户端 <----[SYN,ACK: Seq=y,Ack=x+1]---- 服务端
客户端 -----[ACK: Seq=x+1,Ack=y+1]-----> 服务端
2. 客户端发送数据
假设客户端向服务端发送了100字节数据:
客户端 -----[PSH,ACK: Seq=x+1,Ack=y+1,Len=100]-----> 服务端
- PSH(Push)标志:表示应立即将数据交付给应用层
- Seq=x+1:从握手结束后的序列号开始
- Ack=y+1:确认服务端最后发送的序号
- Len=100:包含100字节的数据
3. 服务端确认接收
客户端 <-----[ACK: Seq=y+1,Ack=x+1+100]-------- 服务端
- Seq=y+1:服务端的序列号保持不变
- Ack=x+1+100:确认收到了客户端发送的100字节数据,期望下一个序列号为 x+1+100
4. 服务端发送响应数据
假设服务端响应200字节数据:
客户端 <-----[PSH,ACK: Seq=y+1,Ack=x+101,Len=200]-------- 服务端
- Seq=y+1:从服务端序列号开始
- Ack=x+101:确认已收到客户端的所有数据
- Len=200:包含200字节的响应数据
5. 客户端确认接收
客户端 -----[ACK: Seq=x+101,Ack=y+1+200]-----> 服务端
- Seq=x+101:客户端的新序列号 (x+1+100)
- Ack=y+1+200:确认收到服务端的200字节数据,期望下一个序列号为 y+1+200
实际捕获示例
以下是三次握手后数据交换的典型 Wireshark 抓包示例:
TCP 74 58618 → 20880 [PSH, ACK] Seq=1 Ack=1 Win=2619648 Len=30
TCP 44 20880 → 58618 [ACK] Seq=1 Ack=31 Win=2619648 Len=0
TCP 244 20880 → 58618 [PSH, ACK] Seq=1 Ack=31 Win=2619648 Len=200
TCP 44 58618 → 20880 [ACK] Seq=31 Ack=201 Win=2619648 Len=0
关键特性
-
序列号增长:每发送的数据字节都会增加发送方的序列号
- 如果发送 N 字节,下一个包的 Seq = 当前 Seq + N
-
即时确认:通常接收方会尽快发送 ACK 确认收到的数据
- 但也可能使用延迟确认策略,等待一段时间或凑齐某个数量再确认
-
数据分段:大量数据可能会被分成多个 TCP 段发送
- 每个段的大小不超过 MSS(最大段大小)
窗口滑动:Win 字段表示接收窗口大小,控制发送速率
-
交互模式:
- 全双工通信:双方可以同时发送数据
- 请求-响应模式:一方发送请求,另一方发送响应
Dubbo 应用场景
对于 Dubbo 这样的 RPC 框架,三次握手后的消息交换通常包括:
- 客户端发送 RPC 请求(包含方法名、参数等序列化数据)
- 服务端处理请求并发送响应结果
- 如果是短连接,完成一次请求后会发起四次挥手关闭连接
- 如果是长连接,连接会被保持,用于后续请求
这种请求-响应模式通常会在 TCP 段中看到 PSH 标志,表示数据应尽快交给应用层处理。