TCP状态转换图详解:11种状态的完整推导

前言

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后)

时序图

客户端 服务端 CLOSED CLOSED listen() LISTEN SYN SYN_SENT SYN+ACK SYN_RCVD ACK ESTABLISHED ESTABLISHED 客户端 服务端

哈吉米:“客户端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 完整的四次挥手

时序图

客户端_主动_ 服务端_被动_ ESTABLISHED ESTABLISHED FIN FIN_WAIT_1 ACK CLOSE_WAIT FIN_WAIT_2 应用层调用close() FIN LAST_ACK ACK TIME_WAIT CLOSED 等待2MSL CLOSED 客户端_主动_ 服务端_被动_

主动关闭 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主动打开发SYNSYN_SENT
CLOSED被动打开-LISTEN
LISTEN收SYN发SYN+ACKSYN_RCVD
SYN_SENT收SYN+ACK发ACKESTABLISHED
SYN_RCVD收ACK-ESTABLISHED
ESTABLISHED主动关闭发FINFIN_WAIT_1
ESTABLISHED收FIN发ACKCLOSE_WAIT
FIN_WAIT_1收ACK-FIN_WAIT_2
FIN_WAIT_2收FIN发ACKTIME_WAIT
CLOSE_WAIT调用close()发FINLAST_ACK
LAST_ACK收ACK-CLOSED
TIME_WAIT等2MSL-CLOSED

七、TCP状态机总结

7.1 核心要点

南北绿豆总结:

  1. 11种状态:1个初始、1个监听、9个转换
  2. 建立连接:3个状态(SYN_SENT/SYN_RCVD/ESTABLISHED)
  3. 关闭连接:6个状态
  4. 主动关闭:TIME_WAIT要等2MSL
  5. 被动关闭: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考研真题

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值