Computer NetworkNotes

第 11 章:TCP 状态机

zjc 于 2026-01-11 发布

这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 TCP 连接有明确的生命周期状态。状态分布是生产排障的重要证据:SYN_RECV 异常可能意味着攻击或队列问题,CLOSE_WAIT 堆积指向应用泄漏,FIN_WAIT 长期挂起可能说明对端或中间链路异常。

11.1 状态总览

                LISTEN
                   |
收到 SYN,发送    | 客户端发送 SYN
SYN+ACK           v
SYN_RECV       SYN_SENT
      |           |
收到 ACK           | 收到 SYN+ACK,发送 ACK
      v           v
       ESTABLISHED
           |
主动 FIN / 被动 FIN
   |             |
   v             v
FIN_WAIT_1    CLOSE_WAIT
   |             |
收到 ACK        应用 close
   v             v
FIN_WAIT_2    LAST_ACK
   |             |
收到 FIN,发送 ACK | 收到 ACK
   v             v
TIME_WAIT      CLOSED
   |
2MSL
   v
CLOSED

11.2 建连阶段状态

状态 位置 含义
LISTEN 服务端 等待连接
SYN_SENT 客户端 已发送 SYN
SYN_RECV 服务端 已收到 SYN 并回复 SYN+ACK

异常:

  1. 客户端长期 SYN_SENT:网络不可达、丢包、防火墙丢包;
  2. 服务端大量 SYN_RECV:SYN Flood、队列满、应用未及时处理;
  3. 客户端收到 RST:端口未监听或策略拒绝;
  4. 握手完成后立即断开:LB 健康检查或应用异常。

查看:

ss -ant state syn-recv
ss -ant state syn-sent

11.3 传输阶段状态

ESTABLISHED 表示连接可用,但不代表业务健康。

观察:

ss -ntp state established
ss -i

关注:

  1. 连接数量;
  2. 进程归属;
  3. 收发队列;
  4. RTT 和重传;
  5. 空闲时间;
  6. 对端地址分布。

11.4 关闭阶段状态

状态 出现位置 含义
FIN_WAIT_1 主动关闭方 已发 FIN,未收到 ACK
FIN_WAIT_2 主动关闭方 收到 ACK,等待对端 FIN
CLOSE_WAIT 被动关闭方 收到 FIN,等待应用 close
LAST_ACK 被动关闭方 已发 FIN,等待最后 ACK
TIME_WAIT 主动关闭方 等待旧报文消失
CLOSING 双方同时关闭 少见

FIN_WAIT_1

长期堆积可能表示 FIN 或 ACK 丢失,以及对端或中间链路异常。

FIN_WAIT_2

主动方已关闭一个方向,等待对端 FIN。若对端应用长期不关闭,连接可能停留。Linux 可通过 FIN_WAIT_2 超时控制孤儿连接回收。

LAST_ACK

被动方发送 FIN 后等待 ACK,如果 ACK 丢失可能停留并重传 FIN。

11.5 状态监控命令

统计状态:

ss -ant | awk 'NR>1 {count[$1]++} END {for (s in count) print s, count[s]}'

查看特定进程:

ss -ntp | grep <pid>

查看监听队列:

ss -lnt

内核统计:

nstat -az | grep -E 'TcpExtListen|TcpRetrans|TcpEstabResets'
netstat -s

11.6 状态与故障定位

状态 常见原因 处理
SYN_SENT 多 出口网络、目标不可达 路由、防火墙、服务监听
SYN_RECV 多 突发建连或攻击 backlog、SYN Cookie、限流
CLOSE_WAIT 多 应用未 close 修复连接泄漏
TIME_WAIT 多 短连接 连接复用、长连接
FIN_WAIT 多 对端或链路异常 抓包和对端排查
ESTABLISHED 过多 连接池失控 上限、隔离、审计

11.7 同时打开与同时关闭

同时打开

双方同时向对方发送 SYN,可能进入:

SYN_SENT -> SYN_RECV -> ESTABLISHED

同时打开较罕见,通常出现在对等连接和测试环境中。

同时关闭

双方同时发送 FIN:

ESTABLISHED -> FIN_WAIT_1 -> CLOSING -> TIME_WAIT

11.8 状态机排障案例

案例 1:服务偶发连接失败

现象:

客户端 SYN 超时
服务端 CPU 正常
SYN_RECV 突增
listen overflow 增长

处理:

  1. 增大 backlog;
  2. 检查应用 accept 循环;
  3. 优化线程池;
  4. 前置限流;
  5. 排查重试风暴。

案例 2:重启后 fd 耗尽

现象:

ss -ant state close-wait | wc -l

结果很高,进程重启后恢复,运行数小时再次耗尽。

根因通常是异常分支没有关闭 socket 或 HTTP 响应体。修复资源释放,而不是单纯增大 fd 上限。

本章小结

TCP 状态机描述连接从监听、握手、传输到关闭的生命周期。建连阶段重点看 SYN_SENT、SYN_RECV 和监听队列;传输阶段看 ESTABLISHED 与重传;关闭阶段用 TIME_WAIT 和 CLOSE_WAIT 区分短连接与连接泄漏。状态分布结合进程、fd、队列和抓包,可以快速定位网络或应用责任。

思考题

  1. 画出客户端和服务端完整的 TCP 状态迁移图。
  2. CLOSE_WAIT 出现在哪一方?为什么?
  3. 哪些证据能判断服务端监听队列溢出?
  4. FIN_WAIT_2 长期存在说明什么?
  5. 设计一套 TCP 状态监控告警规则。