TCP的有限状态机(TCP Finite State Machine)详解
字数 2436 2025-11-09 07:02:43

TCP的有限状态机(TCP Finite State Machine)详解

TCP连接的生命周期由一系列状态变化构成,这个状态变化的集合就是TCP有限状态机。理解状态机对于诊断网络连接问题、分析抓包数据至关重要。

一、状态机的基本构成

TCP状态机包含11种标准状态,分布在连接的建立(三次握手)、数据传输和终止(四次挥手)三个阶段。每个状态都代表连接的一个特定阶段。

二、连接建立阶段的状态流转(三次握手)

这个过程涉及客户端和服务器端状态的协同变化。

  1. 初始状态

    • 服务器端:启动服务后,监听特定端口,进入 LISTEN 状态,等待客户端的连接请求。
  2. 第一次握手(客户端发起)

    • 客户端:应用程序(如浏览器)调用 connect() 系统调用。操作系统内核会构建一个SYN标志位设置为1的TCP报文段并发送出去。随后,客户端连接进入 SYN-SENT 状态。
    • 状态含义SYN-SENT 表示“已发送SYN报文,正在等待对端的SYN-ACK应答”。此时,连接尚未建立,但客户端已经发起了请求。
  3. 第二次握手(服务器端响应)

    • 服务器端:在 LISTEN 状态下收到客户端的SYN报文后,会做出两件事:
      a. 将该连接信息放入一个名为“半连接队列”(或SYN队列)的内核数据结构中。
      b. 回复一个SYN-ACK报文(SYN和ACK标志位均设为1)。然后,服务器端的该连接状态变为 SYN-RECEIVED
    • 状态含义SYN-RECEIVED 表示“已收到并确认了对方的SYN,同时也发送了自己的SYN,正在等待对方的最终ACK”。此时,服务器端认为连接即将建立,但还需要最后一步确认。
  4. 第三次握手(客户端确认)

    • 客户端:在 SYN-SENT 状态下收到服务器的SYN-ACK报文后,会进行确认:
      a. 确认序列号有效。
      b. 发送一个ACK报文(ACK标志位设为1)。
      c. 连接状态从 SYN-SENT 转变为 ESTABLISHED
    • 服务器端:在 SYN-RECEIVED 状态下收到客户端的ACK报文后,会进行确认:
      a. 验证ACK的有效性。
      b. 将该连接从“半连接队列”移入“全连接队列”(或ACCEPT队列)。
      c. 当服务器应用程序调用 accept() 系统调用时,内核从全连接队列中取出这个连接,服务器端的连接状态也随之变为 ESTABLISHED
    • 最终状态ESTABLISHED 表示“连接已建立,双方可以开始双向数据传输”。这是连接的生命周期中持续时间最长的状态。

三、连接终止阶段的状态流转(四次挥手)

连接的关闭可以由任意一方发起,我们以客户端主动关闭为例。

  1. 第一次挥手(主动关闭方发起)

    • 客户端:应用程序调用 close() 系统调用。内核发送一个FIN报文(FIN标志位设为1),表示数据发送完毕。客户端状态从 ESTABLISHED 变为 FIN-WAIT-1
    • 状态含义FIN-WAIT-1 表示“已发送FIN,等待对方的ACK确认,也可能同时等待对方的FIN”。
  2. 第二次挥手(被动关闭方响应ACK)

    • 服务器端:在 ESTABLISHED 状态下收到FIN报文后,会立即回复一个ACK报文进行确认。然后,服务器端状态变为 CLOSE-WAIT
    • 客户端:在 FIN-WAIT-1 状态下收到这个ACK后,状态变为 FIN-WAIT-2
    • 状态含义
      • CLOSE-WAIT:表示“已收到对方的关闭请求(FIN),并已确认。本机正在等待应用程序调用close()来关闭连接”。此时,服务器端到客户端的方向可能还有数据要发送(半关闭状态)。
      • FIN-WAIT-2:表示“已收到对方对FIN的确认。现在正在等待对方发送FIN报文”。
  3. 第三次挥手(被动关闭方发起FIN)

    • 服务器端:当应用程序也调用 close() 后,内核会发送一个FIN报文。服务器端状态从 CLOSE-WAIT 变为 LAST-ACK
    • 状态含义LAST-ACK 表示“已发送自己的FIN,正在等待对方最后一个ACK确认”。
  4. 第四次挥手(主动关闭方响应ACK)

    • 客户端:在 FIN-WAIT-2 状态下收到服务器的FIN报文后,会发送一个ACK报文进行确认。然后,客户端状态变为 TIME-WAIT
    • 服务器端:在 LAST-ACK 状态下收到ACK后,连接即被关闭,状态变为 CLOSED
    • 关键状态TIME-WAIT 也称为2MSL等待状态。
      • 目的:主要有两个:1) 确保最后一个ACK能到达服务器端(如果丢失,服务器会重传FIN,客户端可以再次发送ACK)。2) 让本次连接持续时间内产生的所有网络报文都在网络中消失,避免与未来新的、相同四元组(源IP、源端口、目的IP、目的端口)的连接收到旧的、延迟的报文,造成数据错乱。
      • 时长:持续时间通常是2倍的最大报文段生存时间(2MSL),在Linux下一般为60秒。超时后,客户端状态变为 CLOSED,连接彻底结束。

四、异常状态

  • CLOSING:一种相对罕见的状态。表示双方同时发送FIN(同时开始关闭连接),并都进入了 FIN-WAIT-1 状态。当双方都收到对方的FIN(而非ACK)时,就会进入 CLOSING 状态。在收到对方的ACK后,会进入 TIME-WAIT 状态。

总结
TCP有限状态机精确地描述了TCP连接从生到死的每一个步骤。排查网络问题时(如使用 netstatss 命令看到大量 TIME-WAITCLOSE-WAIT),通过分析连接所处的状态,可以快速定位问题根源(例如,大量 CLOSE-WAIT 可能意味着服务器应用程序没有正确调用 close())。

TCP的有限状态机(TCP Finite State Machine)详解 TCP连接的生命周期由一系列状态变化构成,这个状态变化的集合就是TCP有限状态机。理解状态机对于诊断网络连接问题、分析抓包数据至关重要。 一、状态机的基本构成 TCP状态机包含11种标准状态,分布在连接的建立(三次握手)、数据传输和终止(四次挥手)三个阶段。每个状态都代表连接的一个特定阶段。 二、连接建立阶段的状态流转(三次握手) 这个过程涉及客户端和服务器端状态的协同变化。 初始状态 服务器端 :启动服务后,监听特定端口,进入 LISTEN 状态,等待客户端的连接请求。 第一次握手(客户端发起) 客户端 :应用程序(如浏览器)调用 connect() 系统调用。操作系统内核会构建一个SYN标志位设置为1的TCP报文段并发送出去。随后,客户端连接进入 SYN-SENT 状态。 状态含义 : SYN-SENT 表示“已发送SYN报文,正在等待对端的SYN-ACK应答”。此时,连接尚未建立,但客户端已经发起了请求。 第二次握手(服务器端响应) 服务器端 :在 LISTEN 状态下收到客户端的SYN报文后,会做出两件事: a. 将该连接信息放入一个名为“半连接队列”(或SYN队列)的内核数据结构中。 b. 回复一个SYN-ACK报文(SYN和ACK标志位均设为1)。然后,服务器端的该连接状态变为 SYN-RECEIVED 。 状态含义 : SYN-RECEIVED 表示“已收到并确认了对方的SYN,同时也发送了自己的SYN,正在等待对方的最终ACK”。此时,服务器端认为连接即将建立,但还需要最后一步确认。 第三次握手(客户端确认) 客户端 :在 SYN-SENT 状态下收到服务器的SYN-ACK报文后,会进行确认: a. 确认序列号有效。 b. 发送一个ACK报文(ACK标志位设为1)。 c. 连接状态从 SYN-SENT 转变为 ESTABLISHED 。 服务器端 :在 SYN-RECEIVED 状态下收到客户端的ACK报文后,会进行确认: a. 验证ACK的有效性。 b. 将该连接从“半连接队列”移入“全连接队列”(或ACCEPT队列)。 c. 当服务器应用程序调用 accept() 系统调用时,内核从全连接队列中取出这个连接,服务器端的连接状态也随之变为 ESTABLISHED 。 最终状态 : ESTABLISHED 表示“连接已建立,双方可以开始双向数据传输”。这是连接的生命周期中持续时间最长的状态。 三、连接终止阶段的状态流转(四次挥手) 连接的关闭可以由任意一方发起,我们以客户端主动关闭为例。 第一次挥手(主动关闭方发起) 客户端 :应用程序调用 close() 系统调用。内核发送一个FIN报文(FIN标志位设为1),表示数据发送完毕。客户端状态从 ESTABLISHED 变为 FIN-WAIT-1 。 状态含义 : FIN-WAIT-1 表示“已发送FIN,等待对方的ACK确认,也可能同时等待对方的FIN”。 第二次挥手(被动关闭方响应ACK) 服务器端 :在 ESTABLISHED 状态下收到FIN报文后,会立即回复一个ACK报文进行确认。然后,服务器端状态变为 CLOSE-WAIT 。 客户端 :在 FIN-WAIT-1 状态下收到这个ACK后,状态变为 FIN-WAIT-2 。 状态含义 : CLOSE-WAIT :表示“已收到对方的关闭请求(FIN),并已确认。本机正在等待应用程序调用 close() 来关闭连接”。此时,服务器端到客户端的方向可能还有数据要发送(半关闭状态)。 FIN-WAIT-2 :表示“已收到对方对FIN的确认。现在正在等待对方发送FIN报文”。 第三次挥手(被动关闭方发起FIN) 服务器端 :当应用程序也调用 close() 后,内核会发送一个FIN报文。服务器端状态从 CLOSE-WAIT 变为 LAST-ACK 。 状态含义 : LAST-ACK 表示“已发送自己的FIN,正在等待对方最后一个ACK确认”。 第四次挥手(主动关闭方响应ACK) 客户端 :在 FIN-WAIT-2 状态下收到服务器的FIN报文后,会发送一个ACK报文进行确认。然后,客户端状态变为 TIME-WAIT 。 服务器端 :在 LAST-ACK 状态下收到ACK后,连接即被关闭,状态变为 CLOSED 。 关键状态 : TIME-WAIT 也称为2MSL等待状态。 目的 :主要有两个:1) 确保最后一个ACK能到达服务器端(如果丢失,服务器会重传FIN,客户端可以再次发送ACK)。2) 让本次连接持续时间内产生的所有网络报文都在网络中消失,避免与未来新的、相同四元组(源IP、源端口、目的IP、目的端口)的连接收到旧的、延迟的报文,造成数据错乱。 时长 :持续时间通常是2倍的最大报文段生存时间(2MSL),在Linux下一般为60秒。超时后,客户端状态变为 CLOSED ,连接彻底结束。 四、异常状态 CLOSING :一种相对罕见的状态。表示双方同时发送FIN(同时开始关闭连接),并都进入了 FIN-WAIT-1 状态。当双方都收到对方的FIN(而非ACK)时,就会进入 CLOSING 状态。在收到对方的ACK后,会进入 TIME-WAIT 状态。 总结 TCP有限状态机精确地描述了TCP连接从生到死的每一个步骤。排查网络问题时(如使用 netstat 或 ss 命令看到大量 TIME-WAIT 、 CLOSE-WAIT ),通过分析连接所处的状态,可以快速定位问题根源(例如,大量 CLOSE-WAIT 可能意味着服务器应用程序没有正确调用 close() )。