zoukankan      html  css  js  c++  java
  • TCP四次挥手为何需要TIME_WAIT以及为何是2MSL?

    根据第三版《UNIX网络编程 卷1》2.7节,TIME_WAIT状态的主要目的有两个:

    • 优雅的关闭TCP连接,也就是尽量保证被动关闭的一端收到它自己发出去的FIN报文的ACK确认报文;

    • 处理延迟的重复报文,这主要是为了避免前后两个使用相同四元组的连接中的前一个连接的报文干扰后一个连接。

      很明显,要实现上述两个目标,TIME_WAIT状态需要持续一段时间,但这段时间应该是多长呢?

      如果只考虑上述第一个目标,则TIME_WAIT状态需要持续的时间应该参考对端的RTO(重传超时时间)以及MSL(报文在网络中的最大生存时间)来计算而不是仅仅按MSL来计算,因为只要对端没有收到针对FIN报文的ACK,就会一直持续重传FIN报文直到重传超时,所以最能实现完美关闭连接的时长计算方式应该是从对端发送第一个FIN报文开始计时到它最后一次重传FIN报文这段时长加上MSL,但这个计算方式过于保守,只有在所有的ACK报文都丢失的情况下才需要这么长的时间;另外,第一个目标虽然重要,但并不十分关键,因为既然已经到了关闭连接的最后一步,说明在这个TCP连接上的所有用户数据已经完成可靠传输,所以要不要完美的关闭这个连接其实已经不是那么关键了。因此,(我猜)RFC标准的制定者才决定以网络丢包不太严重为前提条件,然后根据第二个目标来计算TIME_WAIT状态应该持续的时长。

    对于刚才说的第二点,如何理解TIME_WAIT状态持续2MSL的时间就可以避免前后两个使用相同四元组的连接中的前一个连接的报文干扰后一个连接呢?

    首先我们需要了解如下要点:

    1. TCP连接中的一端发送了FIN报文之后如果收不到对端针对该FIN的ACK,则会反复多次重传FIN报文,大约持续几分钟;

    2. 被动关闭处于LAST_ACK状态的一端在收到最后一个ACK之后不会发送任何报文,立即进入CLOSED状态;

    3. 主动关闭的一端在收到被动关闭端发送过来的FIN报文并回复ACK之后进入TIME_WAIT状态;

    4. 之所以TIME_WAIT状态需要维持一段时间而不是进入CLOSED状态,是因为需要处理对端可能重传的FIN报文或其它一些因网络原因而延迟的数据报文,不处理这些报文可能导致前后两个使用相同四元组的连接中的后一个连接出现异常(详见UNIX网络编程卷1的2.7节 第三版);

    5. 处于TIME_WAIT状态的一端在收到重传的FIN时会重新计时(rfc793 以及 linux kernel源代码tcp_timewait_state_process函数)。

      下面我们开始分析为什么在发送了最后一个ACK报文之后需要等待2MSL时长来确保没有任何属于当前连接的报文还存活于网络之中(前提是在这2MSL时间内不再收到对方的FIN报文,但即使收到了对端的FIN报文也并不影响我们的讨论,因为如果收到FIN则会回复ACK并重新计时)。

      为了便于描述,我们设想有一个处于拆链过程中的TCP连接,这个连接的两端分别是A和B,其中A是主动关闭连接的一端,因为刚刚向对端发送了针对对端发送过来的FIN报文的ACK,此时正处于TIME_WAIT状态;而B是被动关闭的一端,此时正处于LAST_ACK状态,在收到最后一个ACK之前它会一直重传FIN报文直至超时。随着时间的流逝,A发送给B的ACK报文将会有两种结局:

    1. ACK报文在网络中丢失;如前所述,这种情况我们不需要考虑,因为除非多次重传失败,否则AB两端的状态不会发生变化直至某一个ACK不再丢失。

    2. ACK报文被B接收到。我们假设A发送了ACK报文后过了一段时间t之后B才收到该ACK,则有 0 < t <= MSL。因为A并不知道它发送出去的ACK要多久对方才能收到,所以A至少要维持MSL时长的TIME_WAIT状态才能保证它的ACK从网络中消失。同时处于LAST_ACK状态的B因为收到了ACK,所以它直接就进入了CLOSED状态,而不会向网络发送任何报文。所以晃眼一看,A只需要等待1个MSL就够了,但仔细想一下其实1个MSL是不行的,因为在B收到ACK前的一刹那,B可能因为没收到ACK而重传了一个FIN报文,这个FIN报文要从网络中消失最多还需要一个MSL时长,所以A还需要多等一个MSL。

      综上所述,TIME_WAIT至少需要持续2MSL时长,这2个MSL中的第一个MSL是为了等自己发出去的最后一个ACK从网络中消失,而第二MSL是为了等在对端收到ACK之前的一刹那可能重传的FIN报文从网络中消失。另外,虽然说维持TIME_WAIT状态一段时间有2个目的,但这段时间具体应该多长主要是为了达成上述第二个目的而设计的。

    https://www.cnblogs.com/abozhang/p/10974627.html

  • 相关阅读:
    HDU 5338(ZZX and Permutations-用线段树贪心)
    编程之美-活动中心(三分)
    form的method用get导致中文乱码
    Tomcat: Could not clean server of obsolete files
    Eclipse打开javadoc框
    Java EE各种documentation
    web-project的/WEB-INF/lib
    在jsp里面不要瞎用<!-- -->注释
    [流水账]搜索与web-container版本匹配的jar包
    session的创建与销毁
  • 原文地址:https://www.cnblogs.com/joker1937/p/12487776.html
Copyright © 2011-2022 走看看