为什么会有TIME_WAIT状态存在?
《UNIX网络编程(卷1,第3版)》一书给出了答案:
TCP中TIME_WAIT状态存在的两个原因:
- 可靠地实现TCP全双工连接的终止。
- 允许旧的重复段在网络上过期。
我认为这也是“为什么TIME_WAIT状态需要2MSL长”的答案。
首先看原因1。为了可靠地终止全双工连接,假设客户端在图1中发送的最后一个ACK丢失,服务器将重新发送FIN。为接收到该超时和重传的FIN,客户端需要TIME_WAIT状态;那么TIME_WAIT状态必须是2MSL吗?实际上,这取决于服务器端的FIN超时重传时间RTO。如果RTO小于MSL,则TIME_WAIT状态的MSL就足够了。如果RTO大于2MSL,则TIME_WAIT状态的2MSL不够用,因此只有当RTO位于MSL和2MSL之间时,存在TIME_WAIT状态的原因才是TIME_WAIT时间为2MSL的原因。实际上,通常情况下,RTO比MSL小得多,但考虑最坏情况,RTO为2MSL,因此TIME_WAIT状态是2MSL,以确保最坏情况下也能接收到随时间重传的FIN。
TIME_WAIT时间是2MSL的另一个重要原因是原因2。为了确保连接期间生成的所有数据包都从网络中消失,即在建立新的TCP连接时,该连接的旧重复数据包已经从网络中消失。这里可能会有人问:客户端回复最后一个ACK后,它感觉所有数据包可以在1个MSL的时间内消失,为什么需要2MSL时间使所有数据包都消失?原因是:
假设客户端在1个MSL时间后发送了一个ACK,并且服务器在接收到该ACK之前开始随时间重传FIN,那么如果该FIN消失,则需要2MSL时间。
让我们回顾一下这个过程:
经过以上4个步骤,A现在处于TIME_WAIT阶段,而B处于LAST_ACK阶段。
如果第四步(A回ACK给B)丢失了怎么办?
B会等待1个MSL的时间来等待第四步,但是由于没有得到响应,B将重新执行第三步,并且第三步需要花费1个MSL时间才能到达A。因此,A必须等待2个MSL才能优雅地结束连接。
但还有一个问题,如果第四步再次丢失呢? :)
我对此也有同样的问题。我想到了一种假设。
在极端情况下,假设客户端最后一个ACK花费了MSL才到达服务器端。此时,终点认为这个ACK已经因为MSL超时而消失。因此,服务器端立即重传FIN。为了确保这个FIN可以到达客户端(或者如果不能,我们必须确保它已经消失),我们必须再等待另外一个MSL。
TIME-WAIT状态和2SML计时器存在的两个原因:
如果最后一个确认(ACK)段丢失了,服务器TCP会为最后设置的FIN(结束)位设置一个定时器,假设其FIN丢失并重新发送。如果客户端在2MSL计时器到期之前进入关闭状态并关闭连接,则永远不会收到这个重发的FIN段,因此服务器永远不会收到最终的ACK。服务器无法关闭连接。 2MSL计时器使客户端等待足够长的时间(一个SML)以便确认丢失和FIN到达(另一个SML)。如果在TIME-WAIT状态期间,出现新的FIN,则客户端将发送新的ACK并重新启动2SML计时器。
来自一个连接的重复段可能会出现在下一个连接中。假设客户端和服务器已经关闭了一个连接。在短时间内,他们使用相同的套接字地址(相同的源IP地址和目标IP地址以及相同的源端口号和目标端口号)打开一个新的连接。如果两个连接之间的时间不足够长,先前连接中的重复段可能会出现在这个新连接中,并被解释为属于新连接。为了防止这个问题,TCP要求必须经过2MSL的时间才能发生新的“化身”。