连接关闭的四个中间状态是什么
TCP 关闭是四次挥手,过程中会出现多个短暂状态:主动关闭方先进入 FIN_WAIT_1 等对方确认,收到确认后进入 FIN_WAIT_2 等对方的 FIN;双方几乎同时关闭时会出现 CLOSING;被动关闭方发完自己的 FIN 后进入 LAST_ACK 等最后一个确认。这些状态本身是正常的,只有长时间堆积才说明对端或应用出了问题。
基本信息
| FIN_WAIT_1 | 已发 FIN,等待对方 ACK |
|---|---|
| FIN_WAIT_2 | 收到 ACK,等待对方 FIN |
| CLOSING | 双方同时发起关闭,等待对方对 FIN 的确认 |
| LAST_ACK | 被动关闭方发了 FIN,等待最后确认 |
| 相关参数 | net.ipv4.tcp_fin_timeout 控制 FIN_WAIT_2 的超时兜底 |
| 规范 | RFC 9293 §3.3.2 |
典型使用场景
- 排查连接泄漏:大量 FIN_WAIT_2 往往说明对端应用收到 FIN 却不关闭
- 分析短连接性能:谁先关闭谁就承担 TIME_WAIT 或 FIN_WAIT 的堆积
- 定位客户端卡死:LAST_ACK 长期不消失说明对端已经消失
- 调优代理与网关:不合理地主动关闭短连接会把自己的端口耗尽
- 理解负载均衡的会话清理行为:设备超时清理会让两侧状态不一致
查看与清理中间状态
查看与清理中间状态
ss -tan state fin-wait-1 | head # 查看 FIN_WAIT_1
ss -tan state fin-wait-2 | wc -l # 统计 FIN_WAIT_2 数量
ss -tan state last-ack | wc -l # 统计 LAST_ACK
sysctl net.ipv4.tcp_fin_timeout # FIN_WAIT_2 的超时兜底
ss -s # 汇总各状态连接数
watch -n2 "ss -tan | awk '{print $1}' | sort | uniq -c" # 按状态统计变化状态读法
| 状态 | 在等待什么 | 异常信号 |
|---|---|---|
| FIN_WAIT_1 | 对方对本方 FIN 的 ACK | 长期停留说明对方不响应或链路丢包 |
| FIN_WAIT_2 | 对方的 FIN | 堆积说明对端应用收到 FIN 却不关闭连接 |
| CLOSING | 对方对本方 FIN 的 ACK(同时关闭) | 罕见且短暂,一般无需关注 |
| LAST_ACK | 对方对最后 FIN 的 ACK | 堆积说明对端已消失或不可达 |
FIN_WAIT_2 正常情况下应由对方的 FIN 结束;tcp_fin_timeout 只在该连接已无人管理时兜底回收。因此看到大量 FIN_WAIT_2,先查对端应用为什么收到 FIN 还不关闭,而不是急着调小这个参数。
「谁先 close 谁承担后果」是理解状态堆积的关键:服务端主动关闭大量短连接,TIME_WAIT 会堆积在自己这一侧;若客户端先关,则由客户端承担。