这是《计算机网络 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。
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 |
异常:
- 客户端长期 SYN_SENT:网络不可达、丢包、防火墙丢包;
- 服务端大量 SYN_RECV:SYN Flood、队列满、应用未及时处理;
- 客户端收到 RST:端口未监听或策略拒绝;
- 握手完成后立即断开:LB 健康检查或应用异常。
查看:
ss -ant state syn-recv
ss -ant state syn-sent
11.3 传输阶段状态
ESTABLISHED 表示连接可用,但不代表业务健康。
观察:
ss -ntp state established
ss -i
关注:
- 连接数量;
- 进程归属;
- 收发队列;
- RTT 和重传;
- 空闲时间;
- 对端地址分布。
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 增长
处理:
- 增大 backlog;
- 检查应用 accept 循环;
- 优化线程池;
- 前置限流;
- 排查重试风暴。
案例 2:重启后 fd 耗尽
现象:
ss -ant state close-wait | wc -l
结果很高,进程重启后恢复,运行数小时再次耗尽。
根因通常是异常分支没有关闭 socket 或 HTTP 响应体。修复资源释放,而不是单纯增大 fd 上限。
本章小结
TCP 状态机描述连接从监听、握手、传输到关闭的生命周期。建连阶段重点看 SYN_SENT、SYN_RECV 和监听队列;传输阶段看 ESTABLISHED 与重传;关闭阶段用 TIME_WAIT 和 CLOSE_WAIT 区分短连接与连接泄漏。状态分布结合进程、fd、队列和抓包,可以快速定位网络或应用责任。
思考题
- 画出客户端和服务端完整的 TCP 状态迁移图。
- CLOSE_WAIT 出现在哪一方?为什么?
- 哪些证据能判断服务端监听队列溢出?
- FIN_WAIT_2 长期存在说明什么?
- 设计一套 TCP 状态监控告警规则。