997 字
5 分钟
抓包看懂 TCP 三次握手与四次挥手

三次握手、四次挥手几乎人人会背,但「为什么握手是三次、挥手是四次」「TIME_WAIT 到底在等谁」,离开真实报文很难真正理解。本文用 tcpdump 在本地抓一次完整连接,逐包对照。

准备:抓一次 curl 请求#

开两个终端。终端 A 抓包:

Terminal window
sudo tcpdump -i any -nn 'tcp port 8000 and host 127.0.0.1' -c 20

终端 B 起一个简单的 HTTP 服务并访问它:

Terminal window
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。

每个包在做的事:

  1. SYN:客户端说「我想连接,我的初始序号是 3829000」。
  2. SYN+ACK:服务端说「收到(ack 3829001 = 你的序号+1),我的初始序号是 871000」。
  3. ACK:客户端说「也收到你的了(ack 871001)」。

为什么是三次而不是两次? 因为双方都要确认对方的初始序号。第二次握手把「服务端的 SYN」和「对客户端的 ACK」合并在一个包里,所以三次就够了。只握手两次的话,服务端无法确认客户端真的收到了自己的序号——一个延迟到达的旧 SYN 就可能让服务端白白建立连接浪费资源,三次握手用第三个 ACK 杜绝了这种情况。

数据传输与挥手#

中间 Flags [P.] 的是带数据的包(PSH)。结束时:

IP ...8000 > ...53462: Flags [F.], seq ..., ack ... # 服务端 FIN
IP ...53462 > ...8000: Flags [.], ack ... # 客户端 ACK
IP ...53462 > ...8000: Flags [F.], seq ..., ack ... # 客户端 FIN
IP ...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 里的状态时,你脑子里浮现的会是报文本身。

延伸阅读#

抓包看懂 TCP 三次握手与四次挥手
https://meow.us.kg/posts/tcp-handshake-teardown-capture/
作者
もゆちゃん
发布于
2026-09-17
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取