本文共 2766 字,大约阅读时间需要 9 分钟。
1. TCP的管理定时器
TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。TCP通过在发送时设置一个定时器来解决这种问题。如果当定时器溢出时还没有收到确认,它就重传该数据。对任何实现而言,关键之处就在于超时和重传的策略,即怎样决定超时间隔和如何确定重传的频率。 对每个连接,TCP管理4个不同的定时器。 1) 重传定时器:使用于当希望收到另一端的确认。定时器以及一些相关的问题,如拥塞避免。 2) 坚持( persist )定时器:使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。 3) 保活( keep alive )定时器:可检测到一个空闲连接的另一端何时崩溃或重启。 4) 2MSL定时器:测量一个连接处于 TIME_WAIT状态的时间。
2. 连接建立超时
在建立TCP连接的时候,可能存在很多种情况导致无法建立连接。一种情况就是服务器主机没有处于正常状态。这样的情况就会导致TCP连接超时,对于这种情况的处理那就是超时重发机制。一般来讲第一次超时的时间在5.59~5.93秒之间,然而第二次超时时间就是24.00秒。 这是因为BSD版的TCP软件采用一种500ms。当输入telnet命令后,将建立一个6秒定时器(12个时钟),但它可能在之后的5.5~6秒内的任意时间超时。尽管定时器初始化为12个时钟,但定时计数器会在设置后的第一个0~500ms中的任意时刻减1(这就导致了第一个时钟的时间不是标准的500ms)。从那个时候开始,定时计数器大约每隔500ms减1,但是在第一个500ms内是可变的。当计数器变为0时,6秒的定时器便会超时,此时定时器被重置为24秒(48个时钟)。接下来的这段时间就非常接近24秒,因为他是在内核调用TCP的500ms定时器处理程序时被设置的。之后若是再超时重发时间就会变长变为48s和多个64s。若是最终还是没能建立连接,TCP最终将放弃并发送一个复位信号。 3. 往返时间测量
3.1 根据以往值估计新的RTT
在重传过程中需要使用往返时间,就需要对往返时间进行测量,这是因为TCP超时与重传中最重要的部分就是对一个给定连接的往返时间(RTT)的测量。由于路由器和网络流量均会变化,因此我们认为这个时间可能经常会发生变化, TCP应该跟踪这些变化并相应地改变其超时时间。 首先TCP必须测量在发送一个带有特别序号的字节和接收到包含该字节的确认之间的RTT。 用M表示所测量到的RTT。最初的TCP规范使TCP使用低通过滤器来更新一个被平滑的 RTT估计器(记为O)。 这里的α是一个推荐值为0. 9的
平滑因子。每次进行新测量的时候,这个被平滑的 RTT将得到更新。每个新估计的90%来自前一个估计,而10%则取自新的测量。
该算法在给定这个随RTT的变化而变化的平滑因子的条件下, RFC 793推荐的重传超时时间RTO(Retransmission TimeOut)的值应该设置为
这里的β是一个推荐值为2的时延离散因子。
但是在RTT变化范围很大时,使用这个方法无法跟上这种变化,从而引起不必要的重传。不必要的重传会增加网络的负载。
除了被平滑的RTT估计器,所需要做的还有跟踪RTT的方差。
在往返时间变化起伏很大时,基于均值和方差来计算RTO,将比作为均值的常数倍数来计算 RTO能提供更好的响应。在[Jacobson 1988]中的图5和图6中显示了根据RFC 793计算的某些实际往返时间的RTO和下面考虑了往返时间的方差所计算的RTO的比较结果。正如Jacobson所描述的,均值偏差是对标准偏差的一种好的逼近,但却更容易进行计算(计算标准偏差需要一个平方根)。这就引出了下面用于每个RTT测量M的公式。
这里的
A是被平滑的RTT(均值的估计器)而
D则是被平滑的均值偏差。 Err是刚得到的测量结果与当前的RTT估计器之差。A和D均被用于计算下一个重传时间(RTO)。增量
g起平均作用,取为1/8(0.125)。
偏差的增益是h,取值为0.25。当RTT变化时,较大的偏差增益将使 RTO快速上升。
[Jacobson 1988]指明在计算 RTO时使用2D,但经过后来更深入的研究,[Jacobson1990c]
将该值改为4D,也就是在BSD Net/1的实现中使用的那样。
Jacobson指明了一种使用整数运算来计算这些公式的方法,并被许多实现所采用(这也就是g, h和倍数4均是2的乘方的一个原因,这样一来计算均可
只通过移位操作而不需要乘、除运算来完成)。
将Jacobson与最初的方法比较,我们发现被平滑的均值计算公式是类似的(是1减去增益g),而增益可使用不同的值。而且 Jacobson计算RTO的公式依赖于被平滑的RTT和被平滑的均值偏差,而最初的方法则使用了被平滑的RTT的一个倍数。
3.2 测量RTT
在图21-2左边的时间轴上有三个括号,它们表明为进行RTT计算对哪些报文段进行了计时,并不是所有的报文段都被计时。 在每次调用 500 ms的TCP的定时器例程时,就增加一个计数器来完成计时。这意味着,如果一个报文段的确认在它发送550 ms后到达,则该报文段的往返时间RTT将是1个滴答(即500 ms)或是2个滴答(即1000 ms)。 对每个连接而言,除了这个滴答计数器,报文段中数据的起始序号也被记录下来。当收到一个包含这个序号的确认后,该定时器就被关闭。如果ACK到达时数据没有被重传,则被平滑的RTT和被平滑的均值偏差将基于这个新测量进行更新。 图21-2中连接上的定时器在发送报文段1时启动,并在确认(报文段 2)到达时终止。尽管它的RTT是1.061秒(tcpdump的输出),但插口排错的信息显示该过程经历了 3个TCP时钟滴答,即RTT为1500ms。 下一个被计时的是报文段3。当2.4 ms后传输报文段4时,由于连接的定时器已经被启动,因此该报文段不能被计时。当报文段5到达时,确认了正在被计时的数据。虽然我们从tcpdump的输出结果可以看到其RTT是0.808秒,但它的RTT被计算为1个滴答(500ms)。 定时器在发送报文段6时再次被启动,并在1.015秒后接收到它的确认(报文段10)时终止。测量到的RTT是2个滴答。报文段7和9不能被计时,因为定时器已经被使用。而且,当收到报文段8(第769字节的确认)时,由于该报文段不是正在计时的数据的确认,因此什么也没有进行更新。