本我 · 加载中...

文章背景图

TCP 连接状态机:三次握手与四次挥手背后的细节

2026-08-06
0
-
- 分钟
|

TCP 连接状态机:三次握手与四次挥手背后的细节

从一个面试题说起

"描述一下 TCP 三次握手和四次挥手。"——这是网络方向面试的入门题,但真正能把状态迁移过程讲清楚的人不多。这篇文章不打算重复教科书上的流程图,而是把重点放在为什么要这么做哪些细节容易忽略上。

一、三次握手:建立连接为什么需要三步

报文序列

Client                          Server
  |   SYN seq=x                |
  |--------------------------->|  SYN_SENT → LISTEN
  |   SYN+ACK seq=y ack=x+1    |
  |<---------------------------|  → SYN_RCVD
  |   ACK ack=y+1              |
  |--------------------------->|  → ESTABLISHED

关键点:确认双方都具备收发能力

  • 第一次握手后,Server 知道 Client 能发(但不知道 Client 能否收)
  • 第二次握手后,Client 知道 Server 能收能发(自己也能发能收)
  • 第三次握手后,Server 才知道 Client 能收

两步行不行? 不行。如果只有两次握手,Server 无法确认 Client 收到了自己的 SYN+ACK。假设网络中 SYN 报文超时重传,Client 会发起两次连接请求,如果只有两步握手,Server 会建立两个连接,浪费资源。第三次握手让 Server 能区分"新的连接请求"和"延迟到达的重复报文"。

几个高频考点

  1. seq 初始值为什么要随机:防止伪造和序列号猜测攻击(RFC 1948)
  2. SYN 洪泛攻击:攻击者只发 SYN 不回复 ACK,Server 的半连接队列(syn queue)被打满,合法连接被拒绝
  3. backlog 参数listen(fd, backlog) 的 backlog 决定半连接队列 + 全连接队列的大小,调错会丢连接

二、四次挥手:断开连接为什么需要四步

Client                          Server
  |   FIN seq=u                |
  |--------------------------->|  FIN_WAIT_1 → CLOSE_WAIT
  |   ACK ack=u+1              |
  |<---------------------------|  FIN_WAIT_2
  |   FIN seq=w                |  (Server 处理完剩余数据后)
  |<---------------------------|  → LAST_ACK
  |   ACK ack=w+1              |
  |--------------------------->|  → CLOSED
  |  (等待 2MSL 后关闭)       |

为什么不是三次

因为 TCP 是全双工的,两个方向的数据通道是独立的。Client 发 FIN 只表示"我不再发送数据了",不代表"我不接收数据"。Server 收到 FIN 后还要把剩余数据发完,才能发自己的 FIN。

四次挥手里的第二、三步之间,Server 可能还会发送大量数据,这正是半关闭(half-close)的意义:Client 关闭发送方向,但继续接收方向

TIME_WAIT 为什么要等 2MSL

Client 发出最后的 ACK 后进入 TIME_WAIT 状态,等待 2 倍的报文最大生存时间(MSL,通常 30s-60s)。原因有二:

  1. 保证最后的 ACK 能到达:如果 ACK 丢失,Server 会重发 FIN,Client 需要能再次响应
  2. 让旧连接的报文在网络中消失:防止新连接收到旧连接的延迟报文,造成数据混淆

高频考点

  • 大量 TIME_WAIT 连接:高并发短连接场景下常见,可用 SO_REUSEADDRSO_LINGER 缓解,但别滥用
  • CLOSE_WAIT 堆积:通常是应用层代码 bug——收到 FIN 后没有正确关闭 socket,需要排查程序逻辑

三、连接状态的一瞥:netstat/ss

# 查看所有 TCP 连接状态统计
ss -s

# 查看指定端口的连接状态
ss -tunap | grep :8080

# 查看 TIME_WAIT 数量
ss -tan state time-wait

实际排障中,看到大量 SYN_SENT 说明对端不可达,大量 SYN_RECV 说明对端半连接队列满,大量 ESTABLISHED 但响应慢说明业务层问题。状态机的价值在于,它能帮你把问题快速定位到网络层还是应用层

四、常见误区

  1. 三次握手包含数据发送吗:不包含,握手期间只交换控制报文(除非开启 TCP Fast Open)
  2. 挥手一定是四次吗:正常情况下是四次,但如果 Server 在收到 FIN 时已经无数据可发,可以把 ACK 和 FIN 合并(TFO / 延迟确认优化下可能出现三次)
  3. RST 包是什么:异常情况下用来强制断开连接,例如端口未监听、对端程序崩溃、序列号不合法

结语

TCP 状态机是理解一切网络问题的基础。建议把 netstat -tunapss 用熟,遇到连接问题先看状态,再看日志——绝大多数网络故障都能在状态机里找到答案。

原创

TCP 连接状态机:三次握手与四次挥手背后的细节

本文链接: TCP 连接状态机:三次握手与四次挥手背后的细节

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本文为原创文章,转载请联系作者并注明出处。

评论交流

文章目录