TCP协议中TIMEWAIT状态的分析

概述

TCP释放连接的四次挥手后,主动发起关闭的一方会进入TIMEWAIT状态。一般情况下主动关闭是由客户端发起。

在主动关闭(以下统称客户端,因为比较常见)的一方发送FIN后,其不再向网络中继续发送新的数据。服务器端接收到这个FIN后执行被动关闭,发送接收到FIN的ACK,进程不会再将新的数据写入,只是将缓冲区中没有写完的数据继续发送给客户端。缓冲区数据写入完毕后,服务器端发送FIN告诉客户端数据已经全部写完。客户端接收到这个FIN后发送一个ACK表示已经接收到这个FIN。此时客户端进入TIMEWAIT状态,当服务器接收到最后的那个ACK后,服务器端彻底关闭。TIMEWAIT状态后客户端彻底关闭。

为什么要有TIMEWAIT状态

有两个原因说明了TIMEWAIT状态存的必要性:

  • 可靠的实现TCP连接的终止
  • 保证旧的分组在网络中消逝

由于网络的不可靠性,最后的那个ACK有可能发生丢失,经过一个RTT后,服务器重新发送最后的FIN,此时客户端必须维护状态信息,允许它重新发送最终的ACK。如果没有TIMEWAIT状态,客户端发送最后的ACK后直接进入CLOSED状态,如果ACK丢失,服务器重发FIN,此时客户端会响应RST分节,服务器端会将其解释为一个错误,无法进入CLOSED状态,连接释放失败,占用服务器资源。

由于路由迷途的存在,可能在路由某些分组时发生阻塞,或者循环。此时发送端确认超时重传,最后的迷途中的分组也可能到达接收端,这就可能造成混乱。如果没有TIMEWAIT状态的存在,在一个旧的连接释放后,马上使用原来的IP和端口再次建立新的连接,此时如果旧连接中的那个迷途中的分组到达,会引发不可预计的错误。为了避免这种情况,TCP协议规定不允许处于TIMEWAIT状态的连接发起一个新的连接。TIMEWAIT的时长是2MSL,这保证了这段时间后再建立新的连接时,旧的连接的迷途分组已经消逝。

MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间IP数据包将在网络中消失 。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒。

TIMEWAIT存在的危害

TIMEWAIT状态表示socket可以留存相当长的一段时间,如果客户端快速的建立、释放连接,系统中有很多socket处于TIMEWAIT状态,又因为本地端口数量有限,如果很多端口处于TIMEWAIT状态无法使用,当再次建立新的连接时,可能因为端口缺乏而导致无法建立。


参考资料:
time_wait状态的产生原因,危害,如何避免?
TCP/IP TIME_WAIT状态原理