TCP计时器浅解析

面试的时候,如果你在简历中写上“熟悉TCP/IP协议”,然后面试官就问你“能不能给我简单讲讲TCP/IP的计时器都有哪些作用呀?”,如果连计时器有哪些都不知道,怎敢号称“熟悉”?你总不能跟面试官讲“你说说,我看你说全了没有...”我勒个擦,一脚踢飞

其实,TCP要保证正常工作,至少应该有四种计时器:重传计时器、持久计时器、保活计时器和时间等待计时器。

首先,什么是计时器呢?可以理解成一块闹表,隔一段时间闹一次,提醒TCP干特定的事情。个人理解本质上还是使用硬件时钟计时,系统调用time函数计算时间差实现的(有不同意见欢迎交流)。

然后,具体介绍一下这四种计时器以及TCP为什么非得规定这四个一个不能少。

一、重传计时器

       大家都知道TCP是保证数据可靠传输的。怎么保证的呢?带确认的重传机制。在滑动窗口协议中,接受窗口会在连续收到的包序列中的最后一个包向接收端发送一个ACK,当网络拥堵的时候,发送端的数据包和接收端的ACK包都可能丢失。TCP为了保证数据可靠传输,就规定在重传计时器“时间片”到了以后,如果还没有收到对方的ACK,就重发此包,以避免陷入无限等待中。

       当TCP发送报文段时,就创建该特定报文段的重传计时器。可能发生两种情况:

      1.    若在计时器截止时间到之前收到了对此特定报文段的确认,则撤销此计时器。

      2.    若在收到了对此特定报文段的确认之前计时器截止期到,则重传此报文段,并将计时器复位。

   最后,重传计时器的重传时间是有一套算法计算的,这里就不再介绍了。

二、持久计时器

   先来考虑一种情景:发送端“啪啪啪”向接收端发送包直到接受窗口填满了,然后接受窗口告诉发送方接收窗口满了停止发送数据。此时的状态称为“零窗口”状态,发送端和接收端窗口大小均为零。直到接收TCP发送确认并宣布一个非零的窗口大小。但这个确认可能会丢失。我们知道在TCP中,对确认是不需要发送确认的。若确认丢失了,接收TCP并不知道,而是会认为它已经完成任务了,并等待着发送TCP接着会发送更多的报文段。但发送TCP由于没有收到确认,就等待对方发送确认来通知窗口的大小。双方的TCP都在永远地等待着对方。

要打开这种死锁,TCP为每一个连接使用一个持久计时器。当发送TCP收到一个窗口大小为零的确认时,就启动坚持计时器。当坚持计时器期限到时,发送TCP就发送一个特殊的报文段,叫做探测报文段。这个报文段只有一个字节的数据。它有一个序号,但它的序号永远不需要确认;甚至在计算对其他部分的数据的确认时该序号也被忽略。探测报文段提醒接收TCP:确认已丢失,必须重传。

坚持计时器的值设置为重传时间的数值。但是,若没有收到从接收端来的响应,则需发送另一个探测报文段,并将坚持计时器的值加倍和复位。发送端继续发送探测报文段,将坚持计时器设定的值加倍和复位,直到这个值增大到门限值(通常是60秒)为止。在这以后,发送端每隔60秒就发送一个探测报文段,直到窗口重新打开。

三、保活计时器

    保活计时器使用在某些实现中,用来防止在两个TCP之间的连接出现长时期的空闲。假定客户打开了到服务器的连接,传送了一些数据,然后就保持静默了。也许这个客户出故障了。在这种情况下,这个连接将永远地处理打开状态。

要解决这种问题,在大多数的实现中都是使服务器设置保活计时器。每当服务器收到客户的信息,就将计时器复位。超时通常设置为2小时。若服务器过了2小时还没有收到客户的信息,它就发送探测报文段。若发送了10个探测报文段(每一个相隔75秒)还没有响应,就假定客户出了故障,因而就终止该连接。

这种连接的断开当然不会使用四次握手,而是直接硬性地中断和客户端的TCP连接。

四、时间等待计时器

    时间等待计时器是在四次握手的时候使用的。四次握手的简单过程是这样的:假设客户端准备中断连接,首先向服务器端发送一个FIN的请求关闭包(FIN=final),然后由established过渡到FIN-WAIT1状态。服务器收到FIN包以后会发送一个ACK,然后自己由established进入CLOSE-WAIT。此时通信进入半双工状态,即留给服务器一个机会将剩余数据传递给客户端,传递完后服务器发送一个FIN+ACK的包,表示我已经发送完数据可以断开连接了,接着便进入LAST_ACK阶段。客户端收到以后,发送一个ACK表示收到并同意请求,接着由FIN-WAIT2进入TIME-WAIT阶段。服务器端收到ACK,结束连接。此时(即客户端发送完ACK包以后),客户端还要等待2MSL(MSL=maxinum segment lifetime 最长报文生存时间,2MSL就是两倍MSL)才能真正关闭连接。


那么,为什么要等待2MSL呢?

因为客服端发送的ACK对方可能没有收到,此时服务端就要重发FIN+ACK包,所以2MSL是从客服端发ACK对方没有到然后服务端重发FIN+ACK的最长时间,等2MSL就是为了保证对方已经收到ACK包了。若不然,客户端提早断开的话服务器端一直重发FIN+ACK,永远无法进入CLOSE状态。

时间等待计时器就是用来记2MSL这个时间的,当计时器到了2MSL以后,客服端才能断开连接。

你可能感兴趣的:(TCP计时器浅解析)