文章目录
前言
TCP状态机是传输层的核心。为什么有CLOSE_WAIT和TIME_WAIT两种等待?为什么有11种状态? TCP状态转换图是考研408的必考内容,理解每种状态的触发条件和转换逻辑才能掌握TCP连接管理的本质。
我并没有能力让你成为TCP专家,我只是想让你彻底理解11种TCP状态的含义、主动关闭与被动关闭的状态差异、以及TIME_WAIT为什么要等2MSL。每个状态都会详细推导,讲透本质。
摘要
从"大量CLOSE_WAIT导致资源耗尽"故障出发,剖析TCP状态机的完整转换过程。通过三次握手的3个状态、四次挥手的6个状态、以及异常关闭的CLOSING状态,揭秘TCP连接生命周期的11种状态。配合考研状态判断题详解,给出TCP状态机的透彻理解。
一、从大量CLOSE_WAIT说起
周四早上,哈吉米收到告警:
现象:
服务器监控:
TCP连接数:10000+
其中CLOSE_WAIT:8000+(80%)
应用表现:
响应慢
新连接建立失败
错误日志:
Too many open files
南北绿豆查看连接状态:
$ netstat -an | grep CLOSE_WAIT | wc -l
8234
大量CLOSE_WAIT连接
阿西噶阿西分析:
CLOSE_WAIT状态:
- 对方(客户端)已经关闭连接(发了FIN)
- 本方(服务器)还没关闭
原因:
代码bug,没有调用close()
→ 连接一直停留在CLOSE_WAIT
→ 资源泄漏 ❌
哈吉米:“CLOSE_WAIT是什么状态?TCP有哪些状态?”
南北绿豆:“TCP有11种状态,我们逐个讲解。”
二、TCP的11种状态
南北绿豆:“TCP状态机描述了连接的生命周期。”
2.1 状态列表
1. CLOSED: 关闭状态(初始/最终)
2. LISTEN: 监听状态(服务端)
3. SYN_SENT: 发送SYN后(客户端)
4. SYN_RCVD: 收到SYN后(服务端)
5. ESTABLISHED: 连接建立
6. FIN_WAIT_1: 发送FIN后(主动关闭方)
7. FIN_WAIT_2: 收到FIN的ACK后(主动关闭方)
8. CLOSE_WAIT: 收到FIN后(被动关闭方)
9. LAST_ACK: 发送FIN后(被动关闭方)
10. CLOSING: 双方同时关闭
11. TIME_WAIT: 等待2MSL(主动关闭方)
哈吉米:“11种状态,建立连接3个,关闭连接6个?”
南北绿豆:“对!建立连接简单,关闭连接复杂。”
三、连接建立的3个状态
南北绿豆:“三次握手涉及3个状态。”
3.1 三次握手的状态转换
客户端:
状态转换:
CLOSED(初始)
→ SYN_SENT(发送SYN后)
→ ESTABLISHED(收到SYN+ACK后,发送ACK)
服务端:
状态转换:
CLOSED(初始)
→ LISTEN(调用listen(),开始监听)
→ SYN_RCVD(收到SYN后,发送SYN+ACK)
→ ESTABLISHED(收到ACK后)
时序图:
哈吉米:“客户端2个状态(SYN_SENT→ESTABLISHED),服务端3个状态(LISTEN→SYN_RCVD→ESTABLISHED)。”
四、连接关闭的6个状态
南北绿豆:“四次挥手涉及6个状态,分主动关闭和被动关闭。”
4.1 主动关闭方的状态
状态转换:
ESTABLISHED(连接建立)
→ FIN_WAIT_1(发送FIN后)
→ FIN_WAIT_2(收到对方的ACK后)
→ TIME_WAIT(收到对方的FIN后,发送ACK)
→ CLOSED(等待2MSL后)
4.2 被动关闭方的状态
状态转换:
ESTABLISHED(连接建立)
→ CLOSE_WAIT(收到对方的FIN后,发送ACK)
→ LAST_ACK(发送FIN后)
→ CLOSED(收到ACK后)
4.3 完整的四次挥手
时序图:
主动关闭 vs 被动关闭:
主动关闭方(先发FIN):
ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
被动关闭方(后发FIN):
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
关键区别:
主动方:有TIME_WAIT(等2MSL)
被动方:无TIME_WAIT(直接CLOSED)
哈吉米:“主动关闭要等2MSL,被动关闭直接关。”
五、特殊状态详解
5.1 CLOSE_WAIT:被动方等待
含义:收到对方的FIN,但本方还没调用close()
为什么会停留在CLOSE_WAIT?
场景:
1. 客户端发送FIN(关闭连接)
2. 服务端收到,TCP自动回复ACK
→ 进入CLOSE_WAIT
3. 但应用层代码没调用close()
→ 一直停留在CLOSE_WAIT ❌
原因:
代码bug,忘记关闭连接
修复:
finally {
socket.close(); // 必须关闭
}
大量CLOSE_WAIT的危害:
每个连接占用:
- 文件描述符
- 内存(接收/发送缓冲区)
- 端口号
8000个CLOSE_WAIT:
→ 资源耗尽
→ 新连接无法建立 ❌
哈吉米:“CLOSE_WAIT是被动方的Bug,没调用close()导致。”
5.2 TIME_WAIT:主动方等待2MSL
含义:主动关闭方发送最后的ACK后,等待2MSL
为什么要等2MSL?(之前讲过,再强调)
原因1:确保最后的ACK能到达
最后的ACK丢失
→ 对方超时重传FIN
→ 如果主动方已关闭,无法回ACK ❌
等2MSL:
ACK在路上:最多MSL
FIN重传在路上:最多MSL
总共:2MSL
2MSL后,要么成功,要么失败都处理完 ✅
原因2:防止旧连接数据干扰新连接
等2MSL,旧连接的所有数据包都消失
→ 新连接安全 ✅
TIME_WAIT过多的问题:
高并发短连接:
服务端主动关闭(HTTP 1.0)
→ 大量TIME_WAIT
→ 端口耗尽 ❌
解决:
1. 用长连接(HTTP Keep-Alive)
2. 调整内核参数(tcp_tw_reuse)
3. 让客户端主动关闭
哈吉米:“TIME_WAIT是必要的(保证可靠),但过多会有问题。”
5.3 CLOSING:同时关闭
含义:双方同时发送FIN
罕见场景:
正常:一方先关闭(主动),一方后关闭(被动)
同时关闭:
客户端和服务端同时调用close()
→ 同时发送FIN
状态转换:
ESTABLISHED
→ FIN_WAIT_1(发送FIN)
→ CLOSING(收到对方的FIN,但还没收到自己FIN的ACK)
→ TIME_WAIT(收到ACK后)
→ CLOSED
哈吉米:“CLOSING很少见,只在同时关闭时出现。”
六、TCP状态机完整图
南北绿豆:“把所有状态转换画成图。”
完整状态机(考研必背):
客户端(主动打开、主动关闭):
CLOSED
→ SYN_SENT(发SYN)
→ ESTABLISHED(收SYN+ACK,发ACK)
→ FIN_WAIT_1(发FIN)
→ FIN_WAIT_2(收ACK)
→ TIME_WAIT(收FIN,发ACK)
→ CLOSED(等2MSL)
服务端(被动打开、被动关闭):
CLOSED
→ LISTEN(listen())
→ SYN_RCVD(收SYN,发SYN+ACK)
→ ESTABLISHED(收ACK)
→ CLOSE_WAIT(收FIN,发ACK)
→ LAST_ACK(发FIN)
→ CLOSED(收ACK)
状态转换表格:
| 当前状态 | 事件 | 动作 | 下一状态 |
|---|---|---|---|
| CLOSED | 主动打开 | 发SYN | SYN_SENT |
| CLOSED | 被动打开 | - | LISTEN |
| LISTEN | 收SYN | 发SYN+ACK | SYN_RCVD |
| SYN_SENT | 收SYN+ACK | 发ACK | ESTABLISHED |
| SYN_RCVD | 收ACK | - | ESTABLISHED |
| ESTABLISHED | 主动关闭 | 发FIN | FIN_WAIT_1 |
| ESTABLISHED | 收FIN | 发ACK | CLOSE_WAIT |
| FIN_WAIT_1 | 收ACK | - | FIN_WAIT_2 |
| FIN_WAIT_2 | 收FIN | 发ACK | TIME_WAIT |
| CLOSE_WAIT | 调用close() | 发FIN | LAST_ACK |
| LAST_ACK | 收ACK | - | CLOSED |
| TIME_WAIT | 等2MSL | - | CLOSED |
七、TCP状态机总结
7.1 核心要点
南北绿豆总结:
- 11种状态:1个初始、1个监听、9个转换
- 建立连接:3个状态(SYN_SENT/SYN_RCVD/ESTABLISHED)
- 关闭连接:6个状态
- 主动关闭:TIME_WAIT要等2MSL
- 被动关闭:CLOSE_WAIT要调用close()
7.2 常见状态问题
阿西噶阿西:
大量SYN_SENT:
→ 客户端发SYN,但收不到SYN+ACK
→ 服务端可能挂了或网络不通
大量SYN_RCVD:
→ 服务端收到SYN,但客户端没回ACK
→ SYN flood攻击
大量ESTABLISHED:
→ 正常(有很多活跃连接)
大量CLOSE_WAIT:
→ 代码bug,没调用close() ❌
大量TIME_WAIT:
→ 服务端主动关闭短连接
→ 建议用长连接
7.3 考研重点
南北绿豆:
必考:
✓ 画TCP状态转换图
✓ 给定场景,判断状态
✓ TIME_WAIT为什么2MSL
✓ CLOSE_WAIT vs TIME_WAIT区别
必记:
✓ 11种状态名称
✓ 主动关闭:TIME_WAIT
✓ 被动关闭:CLOSE_WAIT
✓ 握手:3个状态
✓ 挥手:6个状态
哈吉米:“TCP状态机要背熟,考试常考状态转换。”
参考资料:
- RFC 793 - TCP State Machine
- 《计算机网络》- 谢希仁
- 408考研真题
433

被折叠的 条评论
为什么被折叠?



