设置成TIME_WAIT的时刻:四次挥手释放连接的时候,客户端收到FIN,关闭读通道,并将自己状态设置成TIME_WAIT,发送一个ACK给服务器。

主动关闭的Socket端会进入TIME_WAIT状态,并且持续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。

    TIME_WAIT状态存在的理由:

1)可靠地实现TCP全双工连接的终止


    在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。



2)允许老的重复分节(segment)在网络中消逝  


    TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身(incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被无解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。


主动关闭的过程:TIME_WAIT1->TIME_WAIT 2->CLOSED


 被动关闭的过程:CLOSE_WAIT->CLOSED


http关闭的过程是服务器先发出关闭申请,而ftp是客户端发出申请。



tcp timestamps 作用 tcp time wait_tcp timestamps 作用



    1、客户端是调用函数close(),这时,客户端会发送一个FIN给服务器。


    2、服务器收到FIN,关闭套接字读通道,并将自己状态设置为CLOSE_WAIT(表示被动关闭),并返回一个ACK给客户端。


    3、客户端收到ACK,关闭套接字写通道



    这是两次握手,接下来,服务器会调用close()


    1、服务器close(),发送一个FIN到客户端。


    2、客户端收到FIN,关闭读通道,并将自己状态设置成TIME_WAIT,发送一个ACK给服务器。


    3、服务器收到ACK,关闭写通道,并将自己状态设置为CLOSE。


    4、客户端等待两个最大数据传输时间,然后将自己状态设置成CLOSED。



TIME_WAIT状态的作用:


    1、保证全双工通信可靠关闭:如果不设置TIME_WAIT状态,直接设置成CLOSED状态,那么服务器得不到回复,会一直发送FIN给客户端。


    2、保证这次连接的重复数据段从网络中消失。如果不设置,那么最后一个回复的时候,需要建立一个socket,端口号可能跟现在的不一样,服务器就会认为是另外的端口号发来的,从而出现数据混乱。



为什么需要 TIME_WAIT 状态?

假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连接的两个方向(全双工关闭),client必须进入 TIME_WAIT 状态,因为client可能面临重发最终ACK的情形。

{
   先调用close()的一方会进入TIME_WAIT状态
 }



此外,考虑一种情况,TCP实现可能面临先后两个同样的相关五元组。如果前一个连接处在 TIME_WAIT 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理TCP报文时,两个连接互相干扰。使用 SO_REUSEADDR 选项就需要考虑这种情况。

为什么 TIME_WAIT 状态需要保持 2MSL 这么长的时间?

如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不会混淆。



===================================================================================================================

TCP三次握手,相信很多人都懂,但是TCP如何关闭链接的,不知道是否有人关注过,传说中的四次握手?算是吧,不过上面问的是在关闭过程中客户端的套接字状态,其实就是客户端在关闭TCP连接中的状态变化,以下是套接字主动和被动关闭的两个过程:

       主动关闭的过程:TIME_WAIT1->TIME_WAIT 2->CLOSED

      被动关闭的过程:CLOSE_WAIT->CLOSED

       不同的应用层协议,关闭过程可能不同,但是大同小异,比如http关闭的过程是服务器先发出关闭申请,而ftp是客户端发出申请,以下是客户端主动发出关闭申请的ftp过程:

    

tcp timestamps 作用 tcp time wait_tcp timestamps 作用_02


    1、客户端是调用函数close(),这时,客户端会发送一个FIN给服务器。

    2、服务器收到FIN,关闭套接字读通道,并将自己状态设置为CLOSE_WAIT(表示被动关闭),并返回一个ACK给客户端。

    3、客户端收到ACK,关闭套接字写通道

    这是两次握手,接下来,服务器会调用close()

    1、服务器close(),发送一个FIN到客户端。

    2、客户端收到FIN,关闭读通道,并将自己状态设置成TIME_WAIT,发送一个ACK给服务器。

    3、服务器收到ACK,关闭写通道,并将自己状态设置为CLOSE。

    4、客户端等待两个最大数据传输时间,然后将自己状态设置成CLOSED。


TIME_WAIT状态的作用:
    1、保证全双工通信可靠关闭:如果不设置TIME_WAIT状态,直接设置成CLOSED状态,那么服务器得不到回复,会一直发送FIN给客户端。
    2、保证这次连接的重复数据段从网络中消失。如果不设置,那么最后一个回复的时候,需要建立一个socket,端口号可能跟现在的不一样,服务器就会认为是另外的端口号发来的,从而出现数据混乱。