TCP的FIN_WAIT_2状态与关闭等待(CLOSE_WAIT)状态详解
字数 2019 2025-11-08 20:56:50

TCP的FIN_WAIT_2状态与关闭等待(CLOSE_WAIT)状态详解

描述
在TCP连接终止的四次挥手过程中,FIN_WAIT_2和CLOSE_WAIT是两个关键的中间状态。理解它们对于诊断连接关闭异常、资源泄漏(如文件描述符耗尽)等问题至关重要。简单来说,FIN_WAIT_2是主动关闭方在发出FIN并收到ACK后进入的状态,它正在等待对端发送FIN;而CLOSE_WAIT是被动关闭方收到FIN后并发出ACK后进入的状态,它表示本地应用尚未关闭连接。

详细过程

  1. 场景设定与状态位置

    • 假设有两个主机:主机A(主动关闭连接方)和主机B(被动关闭连接方)。
    • 在标准的TCP四次挥手过程中:
      • 第一次挥手:主机A发送FIN报文,进入FIN_WAIT_1状态。
      • 第二次挥手:主机B收到FIN,发送ACK确认,进入CLOSE_WAIT状态。主机A收到这个ACK后,从FIN_WAIT_1状态进入FIN_WAIT_2状态。
      • 第三次挥手:主机B上的应用程序调用close()关闭连接,主机B发送FIN报文,进入LAST_ACK状态。
      • 第四次挥手:主机A收到FIN,发送ACK确认,进入TIME_WAIT状态。主机B收到ACK后,进入CLOSED状态。
  2. FIN_WAIT_2状态详解(主动关闭方-主机A)

    • 含义:主机A已经表达了关闭连接的意愿(发送了FIN),并且对方已经确认收到这个关闭请求(回复了ACK)。现在,主机A正在等待主机B也完成数据的发送,并最终发出它自己的FIN报文来彻底关闭连接。
    • 正常情况:这是一个短暂的中间状态。一旦主机A收到来自主机B的FIN报文,它会立即发送最后一个ACK,然后进入TIME_WAIT状态。
    • 异常情况与风险:如果主机B(被动关闭方)因为应用程序bug、崩溃或负载过高等原因,始终不调用close()来发送FIN报文,那么主机A将永远停留在FIN_WAIT_2状态
    • 系统保护机制:为了防止大量连接永远滞留在FIN_WAIT_2状态导致资源耗尽,操作系统内核通常会为这个状态设置一个超时时间(例如,在Linux中可通过net.ipv4.tcp_fin_timeout参数配置,默认60秒)。如果在这个超时时间内没有收到对端的FIN,内核会强制关闭这个连接。
    • 总结:FIN_WAIT_2是一个“等待对方完成关闭”的状态。其存在是正常的,但长时间存在通常意味着被动关闭方出现了问题。
  3. CLOSE_WAIT状态详解(被动关闭方-主机B)

    • 含义:主机B已经收到了主机A的关闭请求(FIN),并且已经回复了ACK。此时,连接处于半关闭状态:主机A到主机B的方向已经关闭(A不再发送数据),但主机B到主机A的方向仍然是打开的(B还可以继续发送数据)。CLOSE_WAIT状态表示:TCP协议栈已经知晓对端要关闭,正在等待本地的应用程序调用close()来释放连接
    • 正常情况:主机B的应用程序应该检测到对端关闭(例如,read()recv()返回0),然后尽快调用close()来发送FIN报文,从而离开CLOSE_WAIT状态,进入LAST_ACK状态。
    • 异常情况与风险:如果主机B的应用程序没有正确编写,例如在收到文件结束符(EOF)后没有关闭socket,那么这个连接将永远停留在CLOSE_WAIT状态。这个socket占用的资源(如文件描述符、内存)将无法被释放。
    • 严重后果:如果发生大量CLOSE_WAIT连接,会快速消耗掉系统的文件描述符上限,导致应用程序无法再建立新的网络连接或打开文件,也就是常见的“Too many open files”错误。这是服务器程序中一个典型的资源泄漏bug。
    • 总结:CLOSE_WAIT状态是一个“等待应用程序处理关闭”的状态。大量的、持续存在的CLOSE_WAIT连接,几乎总是被动关闭方应用程序的代码缺陷导致的,需要检查代码中是否遗漏了socket的关闭操作。
  4. 问题诊断与关联

    • 诊断工具:使用netstatss命令可以查看连接状态。例如,netstat -an | grep -E ‘(FIN_WAIT_2|CLOSE_WAIT)’
    • 关联分析
      • 如果服务器上出现大量CLOSE_WAIT,说明你的服务器程序(被动关闭方)可能没有正确关闭连接。
      • 如果客户端上出现大量FIN_WAIT_2,而服务器端出现大量CLOSE_WAIT,这通常证实了是服务器端应用程序的问题,导致它没有发送最终的FIN。

通过理解FIN_WAIT_2和CLOSE_WAIT状态的本质,你可以快速定位TCP连接关闭异常的根本原因,特别是CLOSE_WAIT状态,它是判断应用程序是否存在资源泄漏的关键指标。

TCP的FIN_ WAIT_ 2状态与关闭等待(CLOSE_ WAIT)状态详解 描述 在TCP连接终止的四次挥手过程中,FIN_ WAIT_ 2和CLOSE_ WAIT是两个关键的中间状态。理解它们对于诊断连接关闭异常、资源泄漏(如文件描述符耗尽)等问题至关重要。简单来说,FIN_ WAIT_ 2是主动关闭方在发出FIN并收到ACK后进入的状态,它正在等待对端发送FIN;而CLOSE_ WAIT是被动关闭方收到FIN后并发出ACK后进入的状态,它表示本地应用尚未关闭连接。 详细过程 场景设定与状态位置 假设有两个主机:主机A(主动关闭连接方)和主机B(被动关闭连接方)。 在标准的TCP四次挥手过程中: 第一次挥手 :主机A发送FIN报文,进入FIN_ WAIT_ 1状态。 第二次挥手 :主机B收到FIN,发送ACK确认,进入CLOSE_ WAIT状态。主机A收到这个ACK后,从FIN_ WAIT_ 1状态进入 FIN_ WAIT_ 2 状态。 第三次挥手 :主机B上的应用程序调用 close() 关闭连接,主机B发送FIN报文,进入LAST_ ACK状态。 第四次挥手 :主机A收到FIN,发送ACK确认,进入TIME_ WAIT状态。主机B收到ACK后,进入CLOSED状态。 FIN_ WAIT_ 2状态详解(主动关闭方-主机A) 含义 :主机A已经表达了关闭连接的意愿(发送了FIN),并且对方已经确认收到这个关闭请求(回复了ACK)。现在,主机A正在等待主机B也完成数据的发送,并最终发出它自己的FIN报文来彻底关闭连接。 正常情况 :这是一个短暂的中间状态。一旦主机A收到来自主机B的FIN报文,它会立即发送最后一个ACK,然后进入TIME_ WAIT状态。 异常情况与风险 :如果主机B(被动关闭方)因为应用程序bug、崩溃或负载过高等原因,始终不调用 close() 来发送FIN报文,那么主机A将 永远停留在FIN_ WAIT_ 2状态 。 系统保护机制 :为了防止大量连接永远滞留在FIN_ WAIT_ 2状态导致资源耗尽,操作系统内核通常会为这个状态设置一个超时时间(例如,在Linux中可通过 net.ipv4.tcp_fin_timeout 参数配置,默认60秒)。如果在这个超时时间内没有收到对端的FIN,内核会强制关闭这个连接。 总结 :FIN_ WAIT_ 2是一个“等待对方完成关闭”的状态。其存在是正常的,但长时间存在通常意味着被动关闭方出现了问题。 CLOSE_ WAIT状态详解(被动关闭方-主机B) 含义 :主机B已经收到了主机A的关闭请求(FIN),并且已经回复了ACK。此时,连接处于半关闭状态:主机A到主机B的方向已经关闭(A不再发送数据),但主机B到主机A的方向仍然是打开的(B还可以继续发送数据)。CLOSE_ WAIT状态表示: TCP协议栈已经知晓对端要关闭,正在等待本地的应用程序调用 close() 来释放连接 。 正常情况 :主机B的应用程序应该检测到对端关闭(例如, read() 或 recv() 返回0),然后尽快调用 close() 来发送FIN报文,从而离开CLOSE_ WAIT状态,进入LAST_ ACK状态。 异常情况与风险 :如果主机B的应用程序 没有正确编写 ,例如在收到文件结束符(EOF)后没有关闭socket,那么这个连接将 永远停留在CLOSE_ WAIT状态 。这个socket占用的资源(如文件描述符、内存)将无法被释放。 严重后果 :如果发生大量CLOSE_ WAIT连接,会快速消耗掉系统的文件描述符上限,导致应用程序无法再建立新的网络连接或打开文件,也就是常见的“Too many open files”错误。这是服务器程序中一个典型的资源泄漏bug。 总结 :CLOSE_ WAIT状态是一个“等待应用程序处理关闭”的状态。 大量的、持续存在的CLOSE_ WAIT连接,几乎总是被动关闭方应用程序的代码缺陷导致的 ,需要检查代码中是否遗漏了socket的关闭操作。 问题诊断与关联 诊断工具 :使用 netstat 或 ss 命令可以查看连接状态。例如, netstat -an | grep -E ‘(FIN_WAIT_2|CLOSE_WAIT)’ 。 关联分析 : 如果服务器上出现大量CLOSE_ WAIT,说明你的服务器程序(被动关闭方)可能没有正确关闭连接。 如果客户端上出现大量FIN_ WAIT_ 2,而服务器端出现大量CLOSE_ WAIT,这通常证实了是服务器端应用程序的问题,导致它没有发送最终的FIN。 通过理解FIN_ WAIT_ 2和CLOSE_ WAIT状态的本质,你可以快速定位TCP连接关闭异常的根本原因,特别是CLOSE_ WAIT状态,它是判断应用程序是否存在资源泄漏的关键指标。