为什么要有 TIME_WAIT 状态?
TIME_WAIT,俗称 2MSL 等待状态,是 TCP 连接主动关闭一方(通常是客户端,但也可能是服务端)在发送最后一次 ACK 确认报文后,会进入的一个状态。它需要等待 2 倍的最大报文段生存时间后,才会最终进入 CLOSED 状态,释放连接资源。
设计 TIME_WAIT 状态主要有两个核心原因,它们是确保 TCP 协议可靠性的基石:
原因一:可靠地终止 TCP 连接(确保最后的 ACK 能到达对方)
这是最主要的原因。让我们回顾一下 TCP 四次挥手的正常流程:
- 主动关闭方(假设为 A)发送
FIN报文,进入FIN_WAIT_1状态。 - 被动关闭方(B)收到
FIN后,回复ACK,进入CLOSE_WAIT状态。A 收到这个 ACK 后,进入FIN_WAIT_2状态。 - 被动关闭方(B)发送自己的
FIN报文,进入LAST_ACK状态。 - 主动关闭方(A)收到 B 的
FIN后,回复最后一个ACK报文,并进入TIME_WAIT状态。
现在,想象一下如果没有 TIME_WAIT,A 在发送完最后一个 ACK 后,就立即关闭连接。那么:
- 问题场景:A 发出的最后一个 ACK 在网络中丢失了。
- 后果:
- 由于没有收到 ACK,B 会认为自己的
FIN报文 A 没有收到,所以 B 会超时重传这个FIN报文。 - 但是,A 此时已经彻底关闭了连接,处于
CLOSED状态。当 A 收到 B 重传的FIN时,它已经'不认识'这个连接了,因为它已经忘记了过去的事情。 - 根据 TCP 规范,A 会回复一个
RST(重置)报文给 B。 - B 收到
RST后,会将其解释为一个错误,认为连接异常终止,而不是优雅地关闭。
- 由于没有收到 ACK,B 会认为自己的
TIME_WAIT 的作用:
当 A 进入 TIME_WAIT 状态并等待 2MSL 时间,这足以:
- 重传最后的 ACK:如果 B 没有收到最后的 ACK,它会重传
FIN。A 在TIME_WAIT状态下,能够识别出这个FIN是来自旧连接的,于是会重新发送一次 ACK,确保 B 能正确收到并正常关闭。 - 等待所有报文消失:这 2MSL 的时间,足以让这次连接中所有还在网络中'游荡'的延迟报文段(包括那个可能丢失后被重传的
FIN)都因生存时间到期而消失。这样就避免了它们干扰后续使用相同四元组的新连接。
原因二:让旧连接的重复报文段在网络中自然消失(防止影响新连接)
这个原因同样至关重要。TCP 连接是通过一个四元组来唯一标识的:(源 IP,源端口,目的 IP,目的端口)。
假设一个 TCP 连接关闭后,我们立即使用相同的四元组建立一个新的连接。
- 问题场景:旧连接中有一个报文因为网络延迟,在连接关闭后才姗姗来迟,到达了目的地。
- 后果:


