三次握手、四次挥手几乎人人会背,但「为什么握手是三次、挥手是四次」「TIME_WAIT 到底在等谁」,离开真实报文很难真正理解。本文用 tcpdump 在本地抓一次完整连接,逐包对照。
准备:抓一次 curl 请求
开两个终端。终端 A 抓包:
sudo tcpdump -i any -nn 'tcp port 8000 and host 127.0.0.1' -c 20终端 B 起一个简单的 HTTP 服务并访问它:
python3 -m http.server 8000 &curl -s http://127.0.0.1:8000/ > /dev/null(-nn 不做域名/端口名解析,输出更快更直观。)
握手:三个包建立连接
抓到的前三行类似:
IP 127.0.0.1.53462 > 127.0.0.1.8000: Flags [S], seq 3829000, ...IP 127.0.0.1.8000 > 127.0.0.1.53462: Flags [S.], seq 871000, ack 3829001, ...IP 127.0.0.1.53462 > 127.0.0.1.8000: Flags [.], ack 871001, ...标志位对照:[S] = SYN,[.] = 纯 ACK,[S.] = SYN+ACK。
每个包在做的事:
- SYN:客户端说「我想连接,我的初始序号是 3829000」。
- SYN+ACK:服务端说「收到(ack 3829001 = 你的序号+1),我的初始序号是 871000」。
- ACK:客户端说「也收到你的了(ack 871001)」。
为什么是三次而不是两次? 因为双方都要确认对方的初始序号。第二次握手把「服务端的 SYN」和「对客户端的 ACK」合并在一个包里,所以三次就够了。只握手两次的话,服务端无法确认客户端真的收到了自己的序号——一个延迟到达的旧 SYN 就可能让服务端白白建立连接浪费资源,三次握手用第三个 ACK 杜绝了这种情况。
数据传输与挥手
中间 Flags [P.] 的是带数据的包(PSH)。结束时:
IP ...8000 > ...53462: Flags [F.], seq ..., ack ... # 服务端 FINIP ...53462 > ...8000: Flags [.], ack ... # 客户端 ACKIP ...53462 > ...8000: Flags [F.], seq ..., ack ... # 客户端 FINIP ...8000 > ...53462: Flags [.], ack ... # 服务端 ACK为什么挥手是四次? 因为 TCP 是全双工的,两个方向要分别关闭。一端发 FIN 只表示「我没数据要发了」,另一端的 ACK 确认后,反向通道还能继续传数据——这叫半关闭(half-close)。等对端也发 FIN 并收到 ACK,连接才真正结束。HTTP/1.1 短连接里通常是服务端先发 FIN(如本例)。
状态机里的两个常客
TIME_WAIT:主动关闭方在发完最后一个 ACK 后等待 2 倍 MSL(报文最大生存时间,Linux 默认合计约 60 秒)。它在防两件事:最后一个 ACK 丢了可以重发;旧连接的迟到报文不会混进下一条同五元组的新连接。用 ss -tan state time-wait | wc -l 可以统计。高并发短连接的机器上 TIME_WAIT 堆积是正常现象,只有当它耗尽端口资源(ss -s 查看)时才需要调优(如开启 tcp_tw_reuse 或改用长连接),不要盲目调小。
CLOSE_WAIT:被动关闭方收到 FIN 回复 ACK 后进入的状态,意味着「对端已关闭,但本端应用还没调用 close()」。大量 CLOSE_WAIT 几乎总是应用代码没正确关闭连接,属于程序 bug,不是系统参数能调的。
排障场景里的标志位速查
| 现象 | 抓包特征 | 常见原因 |
|---|---|---|
| 连接超时 | 只有 SYN 发出,无回应 | 防火墙丢包、对端不存在 |
| 连接被拒 | SYN 后立即收到 [R.](RST+ACK) | 端口没人监听 |
| 连接突然断开 | 中途出现 [R] | 应用崩溃、中间设备超时 |
| 大量重传 | 同一序号反复出现 | 丢包、链路质量差 |
tcpdump 输出里 ack 值长期不动说明对方数据没被确认,也是定位单向丢包的线索。
小结
握手三次 = 双方各发一次 SYN、各确认一次;挥手四次 = 全双工两个方向各关一次。抓一次包比背十遍定义更有用——下次看到 ss -tan 里的状态时,你脑子里浮现的会是报文本身。
延伸阅读
- RFC 793: Transmission Control Protocol
man 8 tcpdump、man 8 ss- tcpdump 官方教程
分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
最后更新于 ,距今已过 35 天
部分内容可能已过时