linux内核真实维护tcp连接状态机,共12种状态,高频排查聚焦listen、syn_sent、syn_recv、established、close_wait、time_wait六类,每种状态对应明确资源行为与典型异常,如close_wait持续增长表明应用未调用close()导致socket泄漏,time_wait超量提示高并发短连接下端口资源约束。

TCP 连接状态机不是理论模型,而是 Linux 内核真实维护的 socket 生命周期映射,每个状态直接决定该连接能否收发数据、是否占用端口、是否参与重传等行为。掌握状态变迁逻辑,是排查“连不上”“卡死”“端口耗尽”等问题的核心能力。
LISTEN → SYN_RECV → ESTABLISHED:三次握手全过程
服务端启动监听后进入 LISTEN 状态,此时仅等待 SYN 包;收到客户端 SYN 后,内核生成半连接(未完成 accept),状态变为 SYN_RECV,并回复 SYN+ACK;客户端 ACK 到达后,内核将连接移入全连接队列,调用 accept() 后正式进入 ESTABLISHED。
- SYN_RECV 堆积常见于:SYN 队列满(net.core.somaxconn 设置过低)、遭受 SYN Flood、或中间设备丢弃 SYN+ACK
- LISTEN 状态不可连接?检查是否 bind(0.0.0.0) 而非 127.0.0.1,确认防火墙放行 SYN,且无 listen overflows(用 netstat -s | grep "listen oversflows" 查)
ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT:主动关闭路径
当本端调用 close(),内核发送 FIN,进入 FIN_WAIT_1;收到对端 ACK 后转为 FIN_WAIT_2;再收到对端 FIN 后回复 ACK,进入 TIME_WAIT,持续 2MSL(默认 60 秒)以防止网络中延迟的旧报文干扰新连接。
- TIME_WAIT 不是错误,是 TCP 可靠性的必要设计;但单机超 65535 个时可能触发 Cannot assign requested address
- 可通过 ss -tan state time-wait | wc -l 实时统计数量
- 不建议盲目调小 net.ipv4.tcp_fin_timeout,应优先优化连接复用(如 HTTP Keep-Alive)或使用连接池
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED:被动关闭路径
对端发送 FIN 后,本端立即回复 ACK 并进入 CLOSE_WAIT —— 此刻连接已半关闭,但应用层仍需主动调用 close() 才能发 FIN;若长期卡在 CLOSE_WAIT,说明程序未释放 socket。
- CLOSE_WAIT 持续增长 = socket 泄漏:常见于异常分支遗漏 close()、HTTP 客户端未处理超时、异步回调未 cleanup
- 用 ss -tan state close-wait | wc -l 快速确认是否存在泄漏趋势
- 定位方法:结合 lsof -i 查进程句柄 + 代码审计 close() 调用路径
异常状态与关键诊断组合技
状态机停滞往往不是单一原因,需交叉验证:
- 抓包看标志位:tcpdump 抓取 SYN/SYN-ACK/ACK/FIN/RST,确认是否发出或丢失
- ss 统计分布:用 ss -tan | awk '{print $1}' | sort | uniq -c | sort -nr 一眼识别主导异常态
- 内核日志线索:dmesg 或 /var/log/messages 中搜索 TCP: time wait bucket table overflow 或 possible SYN flooding











