情境与实验环境
在网络通信中,TCP协议是可靠传输的基石,而三次握手和四次挥手则是TCP连接建立与关闭的核心机制。为了深入理解这些机制,我搭建了一个简单的实验环境:
- 服务器端:Ubuntu 24.04 (IP: 10.0.0.13),运行Nginx服务
- 客户端:Rocky Linux 9.6 (IP: 10.0.0.12),使用curl工具发起HTTP请求
- 抓包工具:Wireshark,监听VMnet8网卡,开启混杂模式
实验步骤
- 在服务器端启动Nginx服务
- 在客户端执行
curl 10.0.0.13发起HTTP请求 - 使用Wireshark捕获并分析两台机器之间的TCP流量
- 过滤条件:
(ip.src==10.0.0.12 and ip.dst==10.0.0.13) or (ip.src==10.0.0.13 and ip.dst==10.0.0.12)
Wireshark捕获结果分析
1. TCP三次握手(连接建立)
TCP三次握手是为了建立可靠的连接,确保双方都准备好发送和接收数据。从Wireshark捕获结果中,我们可以看到三次握手的完整过程:
第一次握手(SYN)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 222 | 15:50:57.865 | 10.0.0.12 | 10.0.0.13 | TCP | 74 | 47723 → 80 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1650140905 TSecr=0 WS=128 |
分析:
- 客户端(10.0.0.12)向服务器(10.0.0.13)发送SYN(同步)报文段
- 源端口:47723(客户端随机端口)
- 目的端口:80(HTTP服务端口)
- 序列号(Seq):0(初始序列号)
- 窗口大小(Win):64240字节
- MSS(最大报文段长度):1460字节
- SACK_PERM:1(支持选择性确认)
- WS(窗口缩放因子):128
第二次握手(SYN+ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 223 | 15:50:57.868 | 10.0.0.13 | 10.0.0.12 | TCP | 74 | 80 → 47723 [SYN, ACK] Seq=0 Ack=1 Win=65160 Len=0 MSS=1460 SACK_PERM=1 TSval=3118643459 TSecr=1650140906 WS=128 |
分析:
- 服务器收到SYN报文后,回复SYN+ACK报文段
- 序列号(Seq):0(服务器初始序列号)
- 确认号(Ack):1(确认收到客户端的SYN,期望下一个序列号为1)
- 其他字段含义与第一次握手类似
第三次握手(ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 224 | 15:50:57.868 | 10.0.0.12 | 10.0.0.13 | TCP | 66 | 47723 → 80 [ACK] Seq=1 Ack=1 Win=64128 Len=0 TSval=1650140907 TSecr=3118643459 |
分析:
- 客户端收到SYN+ACK后,发送ACK报文段
- 序列号(Seq):1(上次发送的Seq+1)
- 确认号(Ack):1(确认收到服务器的SYN,期望下一个序列号为1)
- 窗口大小:64128字节
2. 数据传输阶段
三次握手完成后,TCP连接建立,开始数据传输:
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 225 | 15:50:57.868 | 10.0.0.12 | 10.0.0.13 | HTTP | 163 | GET / HTTP/1.1 |
| 226 | 15:50:57.868 | 10.0.0.13 | 10.0.0.12 | TCP | 66 | 80 → 47723 [ACK] Seq=1 Ack=98 Win=65088 Len=0 TSval=3118643459 TSecr=1650140907 |
| 227 | 15:50:57.868 | 10.0.0.13 | 10.0.0.12 | TCP | 1486 | 80 → 47723 [PSH, ACK] Seq=1 Ack=98 Win=65088 Len=1420 TSval=3118643459 TSecr=1650140907 |
| 228 | 15:50:57.868 | 10.0.0.12 | 10.0.0.13 | TCP | 66 | 47723 → 80 [ACK] Seq=98 Ack=1421 Win=62720 Len=0 TSval=1650140907 TSecr=3118643459 |
| 229 | 15:50:57.868 | 10.0.0.13 | 10.0.0.12 | TCP | 354 | 80 → 47723 [PSH, ACK] Seq=1421 Ack=98 Win=65088 Len=288 TSval=3118643459 TSecr=1650140907 |
| 230 | 15:50:57.868 | 10.0.0.12 | 10.0.0.13 | TCP | 66 | 47723 → 80 [ACK] Seq=98 Ack=1709 Win=62464 Len=0 TSval=1650140907 TSecr=3118643459 |
分析:
- 客户端发送HTTP GET请求(帧225),该请求包含在TCP报文段中
- 服务器确认收到请求(帧226),发送TCP ACK报文,这是服务器对客户端HTTP请求的确认,不是数据传输
- 服务器发送HTTP响应数据,分为两个TCP报文段(帧227和229),均使用[PSH, ACK]标志
- 客户端分别确认收到这两个数据报文段(帧228和230),发送TCP ACK报文
- PSH标志指示客户端立即将数据交给应用层,确保HTTP响应能被及时处理
3. TCP四次挥手(连接关闭)
当数据传输完成后,TCP连接需要通过四次挥手来安全关闭:
第一次挥手(FIN+ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 231 | 15:51:21.812 | 10.0.0.13 | 10.0.0.12 | TCP | 66 | 80 → 47723 [FIN, ACK] Seq=1709 Ack=98 Win=65088 Len=0 TSval=3118646409 TSecr=1650140907 |
分析:
- 服务器(10.0.0.13)发送FIN+ACK报文,请求关闭连接
- 序列号(Seq):1709(上次发送的Seq+1)
- 确认号(Ack):98(确认收到客户端的最后一个数据)
- FIN标志表示服务器不再发送数据
- 时间戳显示,服务器在数据传输完成后(约24秒后)才发起关闭连接请求
第二次挥手(ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 232 | 15:51:21.812 | 10.0.0.12 | 10.0.0.13 | TCP | 66 | 47723 → 80 [ACK] Seq=98 Ack=1710 Win=62464 Len=0 TSval=1650143859 TSecr=3118646409 |
分析:
- 客户端收到FIN+ACK后,立即发送ACK确认
- 序列号(Seq):98(上次发送的Seq+1)
- 确认号(Ack):1710(确认收到服务器的FIN,期望下一个序列号为1710)
- 此时服务器到客户端的连接半关闭
第三次挥手(FIN+ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 233 | 15:51:21.814 | 10.0.0.12 | 10.0.0.13 | TCP | 66 | 47723 → 80 [FIN, ACK] Seq=98 Ack=1710 Win=62464 Len=0 TSval=1650143861 TSecr=3118646409 |
分析:
- 客户端发送FIN+ACK报文,请求关闭客户端到服务器的连接
- 序列号(Seq):98(上次发送的Seq+1)
- 确认号(Ack):1710(确认收到服务器的FIN)
第四次挥手(ACK)
| 帧号 | 时间 | 源IP | 目的IP | 协议 | 长度 | 信息 |
|---|---|---|---|---|---|---|
| 234 | 15:51:21.814 | 10.0.0.13 | 10.0.0.12 | TCP | 66 | 80 → 47723 [ACK] Seq=1710 Ack=99 Win=65088 Len=0 TSval=3118646411 TSecr=1650143861 |
分析:
- 服务器收到FIN+ACK后,立即发送ACK确认
- 序列号(Seq):1710(上次发送的Seq+1)
- 确认号(Ack):99(确认收到客户端的FIN,期望下一个序列号为99)
- 此时客户端到服务器的连接也半关闭,整个TCP连接完全关闭
TCP三次握手与四次挥手的原理深度解析
1. 为什么需要三次握手?
三次握手的主要目的是防止失效的连接请求报文段被服务端接收,从而产生错误。
- 第一次握手:客户端发送SYN,服务器知道客户端发送能力正常
- 第二次握手:服务器发送SYN+ACK,客户端知道服务器接收和发送能力正常
- 第三次握手:客户端发送ACK,服务器知道客户端接收能力正常
通过三次握手,双方都确认了对方的收发能力,确保了连接的可靠性。
2. 为什么需要四次挥手?
四次挥手是因为TCP连接是全双工的,需要分别关闭两个方向的连接:
- 第一次挥手:服务器发送FIN,关闭服务器到客户端的数据传输
- 第二次挥手:客户端发送ACK,确认收到服务器的FIN
- 第三次挥手:客户端发送FIN,关闭客户端到服务器的数据传输
- 第四次挥手:服务器发送ACK,确认收到客户端的FIN
3. 关键标志位含义
| 标志位 | 英文全称 | 含义 |
|---|---|---|
| SYN | Synchronize Sequence Numbers | 同步序列号,用于建立连接 |
| ACK | Acknowledgment Number | 确认序列号,用于确认收到数据 |
| FIN | Finish | 结束,用于关闭连接 |
| PSH | Push | 推送,指示接收方立即将数据交给应用层 |
| RST | Reset | 重置,用于强制关闭连接 |
| URG | Urgent | 紧急,指示紧急数据 |
实验结论
通过本次实验,我们直观地观察到了TCP三次握手和四次挥手的完整过程,验证了TCP协议的可靠性机制:
- 三次握手确保了双方都准备好进行数据传输
- 四次挥手安全地关闭了全双工连接
- ACK确认机制保证了数据的可靠传输
- 窗口机制实现了流量控制
TCP协议的这些设计,确保了在不可靠的网络环境中实现可靠的数据传输。理解这些机制对于网络工程师和SRE来说至关重要,有助于排查网络问题、优化网络性能。
进一步思考
- 如果TCP三次握手只进行两次会发生什么?
- 四次挥手过程中,TIME_WAIT状态的作用是什么?
- 如何通过Wireshark分析TCP连接的性能问题?
- TCP协议的可靠性机制对现代网络架构有何影响?
通过不断深入学习和实验,我们可以更好地理解网络协议的工作原理,为构建可靠、高效的网络系统打下坚实的基础。
文档信息
- 本文作者:soveran zhong
- 本文链接:https://blog.clockwingsoar.cyou/2025/11/27/tcp-three-way-handshake-four-way-wave/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)