2026-08-02 02:53:46 admin 世界杯哥伦比亚

TCP 连接状态详解

TCP 连接状态由 RFC 793 定义,共 11 种标准状态。以下按连接生命周期详细解释:

1. 连接建立阶段

LISTEN (监听)

状态值 :0A(十六进制)/ 10(十进制)

含义:服务器端等待客户端的连接请求

触发条件 :调用 listen() 系统调用后

查看方法 :

bash

复制代码

ss -lnt # 查看所有监听端口

netstat -lnt

典型场景 :

bash

复制代码

# Web服务器监听

Proto Recv-Q Send-Q Local Address:Port Peer Address:Port

tcp 0 0 *:80 *:* LISTEN

SYN-SENT (同步已发送)

状态值 :02 / 2

含义:客户端发送 SYN 后等待服务器回复

触发条件 :调用 connect() 后,发送 SYN 包

持续时间:通常很短(RTT + 处理时间)

问题诊断 :

bash

复制代码

# 大量SYN-SENT可能表示:

# 1. 服务器未响应

# 2. 防火墙阻止

ss -ant | grep -c SYN-SENT

SYN-RECEIVED (同步已接收)

状态值 :03 / 3

别名:SYN-RCVD

含义:服务器收到 SYN,发送 SYN+ACK 后等待客户端 ACK

触发条件:服务器收到 SYN,发送 SYN+ACK 后

半连接队列 :处于此状态的连接在半连接队列(SYN Queue)

安全注意 :SYN Flood 攻击的目标状态

调优参数 :

bash

复制代码

sysctl net.ipv4.tcp_max_syn_backlog # 半连接队列大小

sysctl net.ipv4.tcp_syncookies # 防御SYN Flood

2. 连接已建立阶段

ESTABLISHED (已建立连接)

状态值 :01 / 1

含义:连接已建立,可以正常传输数据

触发条件:完成三次握手后

全连接队列 :从 SYN-RCVD 移入全连接队列(Accept Queue)

查看详细 :

bash

复制代码

# 查看所有已建立连接

ss -nt

# 按进程查看

ss -ntp

数据传输 :

lua

复制代码

客户端 服务器

| ESTABLISHED |

| <-------------------------------> |

| 数据自由流动 |

3. 连接关闭阶段(正常关闭)

FIN-WAIT-1 (结束等待1)

状态值 :04 / 4

含义:主动关闭方发送 FIN 后,等待对方 ACK

触发条件 :调用 close() 或 shutdown(SHUT_WR)

可能转换 :

scss

复制代码

FIN-WAIT-1 → FIN-WAIT-2 # 收到ACK

FIN-WAIT-1 → CLOSING # 同时收到FIN(同时关闭)

FIN-WAIT-1 → TIME-WAIT # 收到FIN+ACK

FIN-WAIT-2 (结束等待2)

状态值 :05 / 5

含义:收到对方对 FIN 的 ACK,等待对方发送 FIN

持续时间:可保持较长时间(对方还未调用 close)

查看 :

bash

复制代码

# 查看处于此状态的连接

ss -ant | grep FIN-WAIT-2

问题 :过多连接可能导致资源耗尽

bash

复制代码

sysctl net.ipv4.tcp_fin_timeout # 默认60秒

CLOSE-WAIT (关闭等待)

状态值 :08 / 8

含义:被动关闭方收到 FIN 后,等待应用层关闭

触发条件:收到对方的 FIN,发送 ACK 后

关键问题 :应用层未及时关闭连接 会导致大量 CLOSE-WAIT

bash

复制代码

# 排查方法

ss -ant | grep CLOSE-WAIT

# 找到对应进程

ss -antp | grep CLOSE-WAIT

# 常见原因:未调用 close(),连接泄漏

CLOSING (正在关闭)

状态值 :0B / 11

含义 :双方同时尝试关闭连接(罕见)

触发条件 :

lua

复制代码

双方几乎同时发送FIN

客户端: FIN-WAIT-1 --发送FIN--> 服务器

服务器: FIN-WAIT-1 --发送FIN--> 客户端

双方收到对方FIN后进入CLOSING

查看 :

bash

复制代码

# 通常很少见

ss -ant | grep -c CLOSING

LAST-ACK (最后确认)

状态值 :09 / 9

含义:被动关闭方发送自己的 FIN 后,等待最后 ACK

触发条件:CLOSE-WAIT 状态的应用调用 close() 后

转换:收到 ACK 后进入 CLOSED

TIME-WAIT (时间等待)

状态值 :06 / 6

含义:主动关闭方收到对方的 FIN 并发送 ACK 后

持续时间 :2MSL (Maximum Segment Lifetime)

默认:60秒(Linux)

查看:sysctl net.ipv4.tcp_fin_timeout

目的 :

确保对方收到最后的 ACK

让旧连接的数据包在网络中消失

查看和管理 :

bash

复制代码

# 统计数量

ss -ant | grep -c TIME-WAIT

# 查看详细信息

ss -ant state time-wait

# 调优参数

sysctl net.ipv4.tcp_tw_reuse # 重用TIME-WAIT连接

sysctl net.ipv4.tcp_tw_recycle # 快速回收(谨慎使用)

sysctl net.ipv4.tcp_max_tw_buckets # 限制数量

4. 特殊/终止状态

CLOSED (关闭)

状态值 :07 / 7

含义:连接完全关闭,无资源占用

注意:统计中通常看不到,因为已释放资源

状态转换图详解

sql

复制代码

+---------+

| CLOSED |

+---------+

被动打开 | 主动打开

LISTEN | SYN-SENT

| | |

v | |

+---------+ | |

| LISTEN | | |

+---------+ | |

收到SYN | | |

发送SYN+ACK | | |

| | |

v | |

+-----------+ | |

|SYN-RECEIVED|<---|--------+

+-----------+ | 收到ACK

收到ACK | | |

| | |

v | |

+---------+ | |

|ESTABLISHED|<--+--------+

+---------+ 连接建立完成

| |

| 应用数据传输 |

| |

| 主动关闭 被动关闭

| 发送FIN 收到FIN

| 发送ACK

v |

+---------+ +-----------+

|FIN-WAIT-1| | CLOSE-WAIT|

+---------+ +-----------+

| |

收到ACK | |应用调用close

v |发送FIN

+---------+ +---------+

|FIN-WAIT-2| |LAST-ACK |

+---------+ +---------+

| |

收到FIN | |收到ACK

发送ACK | |

v v

+---------+ +---------+

|TIME-WAIT| | CLOSED |

+---------+ +---------+

| 等待2MSL

v

+---------+

| CLOSED |

+---------+

完整查看脚本

bash

复制代码

#!/bin/bash

# tcp_state_detailed.sh

# 查看详细的TCP状态统计

echo "================================================"

echo " TCP 连接状态详细统计"

echo "================================================"

echo ""

# 使用 ss 查看(推荐)

echo "【方法1: ss 命令】"

echo "状态 数量 描述"

echo "-----------------------"

ss -ant | awk 'NR>1 {print $2}' | sort | uniq -c | while read count state; do

case $state in

LISTEN) desc="监听端口,等待连接" ;;

SYN-SENT) desc="客户端已发送SYN" ;;

SYN-RECV) desc="服务器收到SYN,已回复SYN+ACK" ;;

ESTAB) desc="连接已建立,数据传输中" ;;

FIN-WAIT-1) desc="主动关闭方发送FIN,等待ACK" ;;

FIN-WAIT-2) desc="收到FIN的ACK,等待对方FIN" ;;

TIME-WAIT) desc="等待2MSL,确保连接完全关闭" ;;

CLOSED) desc="连接完全关闭" ;;

CLOSE-WAIT) desc="被动关闭方收到FIN,等待应用关闭" ;;

LAST-ACK) desc="被动关闭方发送FIN,等待最后ACK" ;;

CLOSING) desc="双方同时尝试关闭" ;;

UNKNOWN) desc="未知状态" ;;

*) desc="" ;;

esac

printf "%-12s %6d %s\n" "$state" "$count" "$desc"

done

echo ""

echo "【方法2: /proc/net/tcp 原始数据】"

echo "状态(十六进制) 数量"

echo "-------------------"

awk '{print $4}' /proc/net/tcp | awk -F: '{print $1}' | sort | uniq -c | sort -rn | while read count hex_state; do

case $hex_state in

0A) state="LISTEN" ;;

01) state="ESTABLISHED" ;;

02) state="SYN_SENT" ;;

03) state="SYN_RECV" ;;

04) state="FIN_WAIT1" ;;

05) state="FIN_WAIT2" ;;

06) state="TIME_WAIT" ;;

07) state="CLOSE" ;;

08) state="CLOSE_WAIT" ;;

09) state="LAST_ACK" ;;

0B) state="CLOSING" ;;

*) state="UNKNOWN($hex_state)" ;;

esac

printf "%-10s %6s %6d\n" "$hex_state" "$state" "$count"

done

echo ""

echo "【关键指标监控】"

total=$(ss -ant | grep -c -v State)

echo "总TCP连接数: $total"

echo ""

# 监控建议

echo "【健康检查建议】"

close_wait=$(ss -ant state close-wait | grep -c -v State)

if [ $close_wait -gt 100 ]; then

echo "⚠️ 警告: CLOSE-WAIT 过多($close_wait),可能存在连接泄漏"

echo " 排查方法:"

echo " 1. ss -antp state close-wait"

echo " 2. 检查对应应用的连接关闭逻辑"

fi

time_wait=$(ss -ant state time-wait | grep -c -v State)

if [ $time_wait -gt 10000 ]; then

echo "⚠️ 警告: TIME-WAIT 过多($time_wait),可能影响新连接"

echo " 优化建议:"

echo " 1. sysctl net.ipv4.tcp_tw_reuse=1"

echo " 2. sysctl net.ipv4.tcp_max_tw_buckets=2000000"

fi

状态诊断与调优

常见问题及解决

问题1:大量 TIME-WAIT

bash

复制代码

# 原因:短连接过多

# 解决:

sysctl -w net.ipv4.tcp_tw_reuse=1 # 重用

sysctl -w net.ipv4.tcp_tw_recycle=1 # 回收(NAT环境慎用)

sysctl -w net.ipv4.tcp_max_tw_buckets=2000000

问题2:大量 CLOSE-WAIT

bash

复制代码

# 原因:应用未正确关闭连接

# 排查:

lsof -nP -iTCP -sTCP:CLOSE_WAIT

# 或

ss -antp state close-wait

# 检查对应进程的代码

问题3:大量 SYN-RECV

bash

复制代码

# 原因:可能遭受SYN Flood攻击

# 防御:

sysctl -w net.ipv4.tcp_syncookies=1

sysctl -w net.ipv4.tcp_max_syn_backlog=4096

sysctl -w net.ipv4.tcp_synack_retries=2

状态监控工具

实时监控脚本

bash

复制代码

#!/bin/bash

# 实时监控TCP状态变化

watch -n 1 '

echo "TCP状态实时监控 - $(date)"

echo "----------------------------------------"

ss -ant | awk '\''NR>1 {count[$2]++} END {

states["LISTEN"]="监听";

states["SYN-SENT"]="发SYN";

states["SYN-RECV"]="收SYN";

states["ESTAB"]="已连接";

states["FIN-WAIT-1"]="等FIN-ACK";

states["FIN-WAIT-2"]="等对方FIN";

states["TIME-WAIT"]="等2MSL";

states["CLOSE-WAIT"]="等应用关";

states["LAST-ACK"]="等最后ACK";

states["CLOSING"]="同时关闭";

for(s in count) {

printf "%-12s %6d %s\n", s, count[s], states[s]

}

}'\'' | sort

'