为什么TIME_WAIT状态需要持续2MSL的时间?

6
在TCP连接中,执行主动关闭的一端需要保持TIME_WAIT状态2MSL时间。为什么确切地需要2MSL呢?许多人说一个MSL用于最终ACK,另一个MSL用于重传FIN。但是,FIN的RTO比MSL短得多,并且FIN不需要等待MSL进行重传。因此,他们的解释对我来说没有意义。有人可以给出一个具体的示例,说明在那段时间内如何交换数据段吗?

在这段时间内,分段不会被交换,并且FIN的RTO只有在它到达时才会比MSL短得多。 - user207421
那么,它防止发生哪种极端情况?一定有一个,对吧? - Cortexiphan
2
它只是确保在端口被释放之前,连接的最后一段确实已经死亡,即超出了其段寿命。也许它不一定要是2 * MSL,也许他们可以指定1.5 * MSL或4 * MSL,但他们没有这样做。 - user207421
6个回答

11

图1:TCP连接的数据包交换

为什么会有TIME_WAIT状态存在?
《UNIX网络编程(卷1,第3版)》一书给出了答案:

TCP中TIME_WAIT状态存在的两个原因:

  1. 可靠地实现TCP全双工连接的终止。
  2. 允许旧的重复段在网络上过期。

我认为这也是“为什么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

让我们回顾一下这个过程:

  1. A发FIN给B
  2. B回ACK给A
  3. B发FIN给A/li>
  4. A回ACK给B

经过以上4个步骤,A现在处于TIME_WAIT阶段,而B处于LAST_ACK阶段。

如果第四步(A回ACK给B)丢失了怎么办?

B会等待1个MSL的时间来等待第四步,但是由于没有得到响应,B将重新执行第三步,并且第三步需要花费1个MSL时间才能到达A。因此,A必须等待2个MSL才能优雅地结束连接。

但还有一个问题,如果第四步再次丢失呢? :)


亲爱的上帝...如果第四步再次丢失怎么办?无限循环?哈哈 - Yves
这个链接可能是你问题的答案。 - KimLikeAStone

1
TIME-WAIT 的目的是防止延迟的数据包被后续的连接所接受。这种情况可能发生在以下情形下:
  1. 从 (地址 a,端口 p) 到 (地址 b,端口 q) 的连接被终止
  2. 从 (地址 a,端口 p) 到 (地址 b,端口 q) 的第二个连接被建立
  3. 来自第一个连接的重复数据包在网络中被延迟,并在其序列号在第二个连接的窗口内时到达第二个连接。
在这种情况下,端点无法确定该数据包属于哪个连接。

1

我对此也有同样的问题。我想到了一种假设。
在极端情况下,假设客户端最后一个ACK花费了MSL才到达服务器端。此时,终点认为这个ACK已经因为MSL超时而消失。因此,服务器端立即重传FIN。为了确保这个FIN可以到达客户端(或者如果不能,我们必须确保它已经消失),我们必须再等待另外一个MSL。


服务器等待RTO,而不是MSL重新传输FIN,对吧?我认为服务器并不关心MSL,它所做的就是重复传输FIN直到收到ACK或FIN重试次数超过。 - Cortexiphan
@Cortexiphan 我认为只有 PSH 会考虑 RTO 进行重传以减少延迟。但是对于 FIN,短暂的延迟并不是那么重要,所以它愿意等待 MSL 来重新传输 FIN。 - hbprotoss

1

TIME-WAIT状态和2SML计时器存在的两个原因:

  1. 如果最后一个确认(ACK)段丢失了,服务器TCP会为最后设置的FIN(结束)位设置一个定时器,假设其FIN丢失并重新发送。如果客户端在2MSL计时器到期之前进入关闭状态并关闭连接,则永远不会收到这个重发的FIN段,因此服务器永远不会收到最终的ACK。服务器无法关闭连接。 2MSL计时器使客户端等待足够长的时间(一个SML)以便确认丢失和FIN到达(另一个SML)。如果在TIME-WAIT状态期间,出现新的FIN,则客户端将发送新的ACK并重新启动2SML计时器。

  2. 来自一个连接的重复段可能会出现在下一个连接中。假设客户端和服务器已经关闭了一个连接。在短时间内,他们使用相同的套接字地址(相同的源IP地址和目标IP地址以及相同的源端口号和目标端口号)打开一个新的连接。如果两个连接之间的时间不足够长,先前连接中的重复段可能会出现在这个新连接中,并被解释为属于新连接。为了防止这个问题,TCP要求必须经过2MSL的时间才能发生新的“化身”。


0
Tcp必须防止旧的重复连接在稍后的时间重新出现,并被误解为属于同一连接的新连接。为此,Tcp不会启动处于TIME_WAIT状态的新连接。
TIME_WAIT状态是MSL的两倍,这允许MSL秒钟内一个方向上的数据包丢失,并且再给另一个MSL秒来丢失回复。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接