对每个连接,TCP管理4个不同的定时器。
1) 重传定时器:使用于当希望收到另一端的确认。
2) 坚持(persist )定时器:使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。
3) 保活(keepalive)定时器:可检测到一个空闲连接的另一端何时崩溃或重启。
4) 2MSL 定时器:测量一个连接处于TIME_WAIT状态的时间。
总结:坚持定时器用于防止通告窗口为0以后双方互相等待死锁的情况;而保活定时器则用于处理半开放连接。
1、坚持定时器
在连接的一方需要发送数据但对方已通告窗口大小为 0时,就需要设置 TCP的坚持定时器。发送方使用与第21章类似的重传间隔时间,不断地探查已关闭的窗口。这个探查过程将一直持续下去。
ACK的传输并不可靠,也就是说, TCP不对ACK报文段进行确认, TCP只确认那些包含有数据的ACK报文段。
如果一个确认丢失了,则双方就有可能因为等待对方而使连接终止:接收方等待接收数据(因为它已经向发送方通告了一个非 0的窗口),而发送方在等待允许它继续发送数据的窗口更新。为防止这种死锁情况的发生,发送方使用一个坚持定时器 (persist timer) 来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查 ( window probe )。
坚持定时器的原理是简单的,当TCP服务器收到了客户端的0滑动窗口报文的时候,就启动一个定时器来计时,并在定时器溢出的时候向向客户端查询窗口是否已经增大,如果得到非零的窗口就重新开始发送数据,如果得到0窗口就再开一个新的定时器准备下一次查询。通过观察可以得知,TCP的坚持定时器使用1,2,4,8,16……64秒这样的普通指数退避序列来作为每一次的溢出时间。
糊涂窗口综合症:
TCP的窗口协议,会引起一种通常叫做糊涂窗口综合症的问题,具体表现为,当客户端通告一个小的非零窗口时,服务器立刻发送小数据给客户端并充满其缓冲区,一来二去就会让网络中充满小TCP数据报,从而影响网络利用率。对于发送方和接收端的这种糊涂行为。TCP给出了一些建议(或者是规定)。
(1)接收方不通告小窗口。通常的算法是接收方不通告一个比当前窗口大的窗口(可以为0),除非窗口可以增加一个报文段大小(也就是将要接收的MSS)或者可以增加接收方缓存空间的一半,不论实际有多少。
(2)发送方避免出现糊涂窗口综合症的措施是只有以下条件之一满足时才发送数据: ( a )可以发送一个满长度的报文段; ( b )可以发送至少是接收方通告窗口大小一半的报文段; ( c )可以发送任何数据并且不希望接收ACK(也就是说,我们没有还未被确认的数据)或者该连接上不能使用Nagle算法。
现在我们发现TCP的很多规定都是为了在一次传送中发送尽量多的数据,例如捎带ACK数据报文的策略,Nagle算法,重传时发送包含原数据报文的策略等等。
2、保活定时器
因为TCP是面向连接的,所以就会出现只连接不传送数据的“半开放连接”,服务器当然要检测到这种连接并且在某些情况下释放这种连接,这就是保活定时器的作用。
在连接两个端系统的网络出现临时故障的时候,保活选项会引起一个实际上很好的连接终止。保活功能主要是为服务器应用程序提供的。服务器应用程序希望知道客户主机是否崩溃,从而可以代表客户使用资源。
保活定时器的缺点:
(1) 在出现短暂差错的情况下,这可能会使一个非常好的连接释放掉;(2)它们耗费不必要的带宽;(3)在按分组计费的情况下会在互联网上花掉更多的钱。然而,许多实现提供了保活定时器。