Time-wait状态(2MSL)一些理解

1. 编写TCP/SOCK 服务时,SO_REUSEADDR究竟是什么意思?服务器

这个套接字选项通知内核,若是端口忙,但TCP状态处于TIME_WAIT,能够重用端口。若是端口忙,TCP状态处于其余状态,重用端口时依旧指明“地址已经在使用中”。若是你的服务程序中止后向马上重启,而新套接字依旧使用同一个端口,此时SO_REUSEADDR选项很是有用。可是必须意识到,此时任何非指望数据到达,均可能致使服务程序反应混乱。网络

一个套接字由五个部分组成:协议,本地地址,本地端口,远程地址和远程端口。SO_REUSEADDR仅仅表示能够重用本地地址,本地端口。并发

2. 为何须要TIME_WAIT状态?socket

假设最后的ACK丢失,server将重发FIN,client必须维护TCP状态信息以即可以重发最后的ACK,不然将会发送RST,结果server认为发生错误。TCP实现必须可靠地终止链接的两个方向,因此client必须进入TIME_WAIT状态。ui

此外,考虑一种状况,TCP实现可能面临着前后两个相同的五元组。若是前一个链接处于TIME_WAIT状态,而容许另外一个拥有相同五元组链接出现,可能处理TCP报文时,两个链接互相干扰。因此使用SO_REUSEADDR选项就须要考虑这种状况。.net

3. 什么是2MSLserver

MSL是Maximum Segment Lifetime,译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
由于TCP报文(segment)是IP数据报(datagram)的数据部分,而IP头中有一个TTL域,TTL是time to live的缩写,中文能够译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间,而是存储了一个IP数据报能够通过的最大路由数,每通过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送ICMP报文通知源主机。
RFC 793中规定MSL为2分钟,实际应用中经常使用的是30秒,1分钟和2分钟等
2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间。
等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后能够再发一个ACK应答包。
在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。
当链接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中能够经过设置SO_REUSEADDR选项达到没必要等待2MSL时间结束再使用此端口。blog

TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。接口

4. 为何TIME_WAIT状态须要保持2MSL这么长的时间?进程

若是TIME_WAIT状态保持时间不足够长,第一个链接就正常终止了。第二个拥有相同五元组的链接出现,而第一个链接的重复报文到达,干扰了第二个链接。TCP事先必须防止某个链接的重复报文在链接终止后出现,因此让TIME_WAIT状态保持时间足够长(2MSL),链接相应方向的上的TCP报文要么彻底响应完毕,要么被丢弃。创建第二个链接的时候,不会混淆。

2MSL等待状态
TIME_WAIT状态也称为2MSL等待状态。每一个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。咱们知道这个时间是有限的,由于TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。
对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该链接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可以让TCP再次发送最后的ACK以防这个ACK丢失(另外一端超时并重发最后的FIN)。
这种2MSL等待的另外一个结果是这个TCP链接在2MSL等待期间,定义这个链接的套接口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个链接只能在2MSL结束后才能再被使用。遗憾的是,大多数TCP实现(如伯克利版)强加了更为严格的限制。在2MSL等待期间,套接口中使用的本地端口在默认状况下不能再被使用。
在链接处于2MSL等待时,任何迟到的报文段将被丢弃。由于处于2MSL等待的、由该套接口对(socket pair)定义的链接在这段时间内不能被再用,所以当要创建一个有效的链接时,来自该链接的一个较早替身( incarnation)的迟到报文段做为新链接的一部分不可能不被曲解(一个链接由一个插口对来定义。一个链接的新的实例( instance)称为该链接的替身)。
客户执行主动关闭并进入TIME_WAIT是正常的。服务器一般执行被动关闭,不会进入TIME_WAIT状态。这暗示若是咱们终止一个客户程序,并当即从新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。这不会带来什么问题,由于客户使用本地端口,而并不关心这个端口号是什么。
然而,对于服务器,状况就有所不一样,由于服务器使用熟知端口。若是咱们终止一个已经创建链接的服务器程序,并试图当即从新启动这个服务器程序,服务器程序将不能把它的这个熟知端口赋值给它的端点,由于那个端口是处于2MSL链接的一部分。在从新启动服务器程序前,它须要在1~4分钟。
尽管许多具体的实现中容许一个进程从新使用仍处于2MSL等待的端口(一般是设置选项SO _REUSEADDR),但TCP不能容许一个新的链接创建在相同的插口对上。

平静时间的概念 对于来自某个链接的较早替身的迟到报文段, 2MSL等待可防止将它解释成使用相同插口对的新链接的一部分。但这只有在处于2MSL等待链接中的主机处于正常工做状态时才有效。若是使用处于2MSL等待端口的主机出现故障,它会在MSL秒内从新启动,并当即使用故障前仍处于2MSL的插口对来创建一个新的链接吗?若是是这样,在故障前从这个链接发出而迟到的报文段会被错误地看成属于重启后新链接的报文段。不管如何选择重启后新链接的初始序号,都会发生这种状况。 为了防止这种状况,RFC 793指出TCP在重启动后的MSL秒内不能创建任何链接。这就称为平静时间(quiet time)。只有极少的实现版遵照这一原则,由于大多数主机重启动的时间都比MSL秒要长。

相关文章
相关标签/搜索