1. 超时重传时间RTO
在前面tcp可靠传输学习中,相信大家都有体会,tcp协议之所以能保证数据到达目的地,主要有两点:一是tcp会对传输的数据进行确认,二是tcp在传输数据过程中会对丢失的数据设置一个超时计时器(超时重传时间,简称RTO
)进行超时重传。
对于超时计时器有以下几点要明白的:
1.当tcp发送了的发送窗口中的报文段时,就会启动这个计时器
2.当计时器超时后,tcp就会重传发送窗口中最前端的报文
,并重启计时器
3.如果tcp中的发送窗口没有没有数据,就停止该计时器,否则将重启计时器
2. 往返时间(RTT)
关于超时重传的时间在停止等待协议中简单提过,超时重传时间的设置是比较复杂的,超时重传时间或大或小都会影响传输效率,但可以肯定的是:超时重传时间设置要比数据报往返时间(往返时间,简称RTT)长一点
。
简单来说,往返时间(RTT)指的其实是一个数据报发送到目的地,然后到发送方收到确认需要多少时间,这就是测量RTT。我们需要记住,发送的报文段和确认的报文并非是一一对应,也有可能是多个发送的报文对应一个确认报文。
注意:在tcp中,任何时刻只能有一个正在进行的RTT测量,一旦开始RTT测量,就不能再进行其他测量。
3. 测量RTT
RTT是随着网络环境而动态变化的,也就是说每次测量RTT都可能有变化,就目前复杂的互联网环境来说,单次的测量RTT值无法被用于超时重传。因此tcp使用了一种加权平均往返时间 RTTS R T T S (又称为平滑的往返时间,这里,我们把加权平均往返时间RTTs统一简称为 RTTS R T T S ,S表示Smoothed,因为进行的是加权平均,因此得出的结果更为平滑)。
第一次测量
RTT时,
RTTS
R
T
T
S
就取所测量到的RTT样本值,即
RTTS=RTT样本
R
T
T
S
=
R
T
T
样
本
。以后每次测量
到一个新的RTT样本,就按下面的公式重新计算一次
RTTS
R
T
T
S
:
在上面的公式中a的取值为: 0≤α≤1 0 ≤ α ≤ 1 ,RFC推荐的 α α 值为1/8,即0.125。通过上面的公式得出的加权平均往返时间RTTs就比直接测量得出的RTT更加平滑,换句话说, 新RTTS 新 R T T S 就是由7/8的 旧RTTS 旧 R T T S 和当前1/8的 RTT R T T (测量的新RTT样本)相加得出的。
值得注意的是,如果
α
α
的取值越小,那么
RTTS
R
T
T
S
更新相对较平稳;反之
α
α
的值越接近于1,则
RTTS
R
T
T
S
更新浮动较大。
3.1 例1
根据上面的公式,来举个例子,当前
RTTS
R
T
T
S
= 300ms,测量到的新RTT样本为900ms,按照上面的公式来计算,
新RTTS
新
R
T
T
S
= (1 - 0.125)x 300ms + 0.125 x 900ms,此时
新RTTS
新
R
T
T
S
值为375ms。也就是说,这里
α
α
的取值是比较小的,因此测量到的新RTT样本较高时,其实对
新RTTS
新
R
T
T
S
影响不大。
3.2 例2
现在,我们再来举个例子,现在设置 α α 的值为0.625,当前 RTTS R T T S 为300ms,测量到的新RTT样本为900ms,根据上面的公式来计算, 新RTTS 新 R T T S = (1 - 0.625)x 300ms + 0.625 x 900ms,此时 新RTTS 新 R T T S 值为675,也就是说,这里 α α 的取值较大,因此测量到的新RTT样本较高时,对 新RTTS 新 R T T S 影响已经是较大了。
那么现在我们知道了往返时间RTT,就可以根据往返时间RTT来设置超时重传时间了。
4. 计算RTT的偏差
这里再说一句,前面我们为了方便,统一把超时重传时间简称为RTO,加权平均往返时间简称为 RTTS R T T S 。
前面我们也说过,超时重传的时间设置的要比往返时间(RTT)要长一些,显然,超时计时器设置的超时重传时间(RTO)应该略大于上面公式中计算出的加权平均往返时间( RTTS R T T S ),意思就是RTO要比 RTTS R T T S 多那么一点点时间。
问题来了,这多出来的一点点时间从哪里来呢???
实际上,上面所说的一点点时间指的是RTT的偏差,其实就是还要计算RTT的偏差,RTT的偏差用
RTTD
R
T
T
D
来表示。好吧,我们姑且把
RTTD
R
T
T
D
认为是要多计算的一点点时间,而事实上它就是这样的。
因此,超时重传时间 = 加权平均往返时间RTTs + 一点点时间 , 于是就有了下面的公式:
再次对在上面的公式解释一遍:超时重传时间 = 加权平均往返时间 RTTS R T T S + 一点点时间,前面说了 RTTD R T T D 是RTT的偏差,其实这有点不太准确,更为正确的说法: RTTD R T T D 是RTT的偏差的加权平均值。
RFC建议这样计算
RTTD
R
T
T
D
:当第一次测量
RTTD
R
T
T
D
时,
RTTD
R
T
T
D
值取为测量到的RTT样本值的一半,公式为:
在以后的每次测量
RTTD
R
T
T
D
中,使用下面的公式加权平均的
RTTD
R
T
T
D
,这样得到的就是更为平滑的
RTTD
R
T
T
D
:
通常 β β 是一个小于1的数,RFC推荐的值为1/4,即0.25 。这里要注意的是:,第一次测量 RTTD R T T D 的公式中,所计算出的 RTTD R T T D 不是平滑的,而每次测量 RTTD R T T D 的公式中所计算出的才更为平滑。
实际上, RTTD R T T D 就是一个均值偏差,它就相当于某个样本到其总体平均值的距离。这就好比你的成绩与你班级平均成绩差了多少。
5. 计算超时重传时间(RTO)
这里,我们再次回到计算平滑 RTTD R T T D 小节中讲过的超时重传时间的计算公式,即 RTO=RTTS+RTTD R T O = R T T S + R T T D 公式,将其更新为 RTO=RTTS+RTTD(平滑) R T O = R T T S + R T T D ( 平 滑 )
也就是说,超时重传时间(RTO)的计算是基于平滑
往返时间(
RTTS
R
T
T
S
)和 平滑
RTTD
R
T
T
D
。那么关于超时重传时间的计算公式,RFC是这样规定的:
通过上面的公式可知,RTO的计算就是RTTs 加上当前平滑的 RTTD R T T D 的4倍。
5.1 通过wireshark工具计算RTO
下面再通过一个例子来说明,我们主要分析双方在tcp建立连接阶段的和发送数据报阶段。如图1所示,当本机访问111.13.100.2站点时会发出tcp连接建立请求。
1. 首先本机发送了第一个SYN报文(第57个报文)后,发送的时间为7.841689000,此时这些变量 RTT R T T , RTTS R T T S , RTTD R T T D 还没有值。假设RTO的值为0.5秒,这些变量的值应该为:
RTT=? R T T = ?
RTTS=? R T T S = ?
RTTD=? R T T D = ?
RTO=0.5 R T O = 0.5
第57个报文的信息如下:
2. 然后到R1收到确认报文(第58个报文),时间为7.873524000。测量出RTT样本 = 7.873524000 - 7.841689000 ,即RTT 样本 = 0.031835000,这时变量的值应该为:
RTT=0.031835000 R T T = 0.031835000
RTTS=0.031835000 R T T S = 0.031835000
RTTD=0.031835000/2=0.015917500 R T T D = 0.031835000 / 2 = 0.015917500
RTO=0.031835000+4×0.015917500=0.095505000 R T O = 0.031835000 + 4 × 0.015917500 = 0.095505000
第58个报文的信息如下:
大家可以根据tcp连接建立时RTO的计算过程,来进行测试计算发送数据报阶段的RTO,由于tcp连接建立的RTO是第一次计算,得到的是初始的RTO,而发送数据阶段的RTO计算得到的应该是更加平滑的RTO,这是它们之间的区别,这也是在进行计算时要注意的地方,也就是注意区分第一次RTO和平滑RTO计算方式的区别。
6. Karn算法

图4-Karn算法
考虑这么一种情况,发送方在时间点1发送了一个M1,假设发送方在超时计时器超时的范围内,即时间点2重传了M1。当发送方在时间点3收到了M1的确认时就懵了,如上图所示,此时发送方不知道这个确认M1到底是对谁的确认,产生了模糊性。
因为新的RTT值要根据报文段发送的时间来计算,如果发送方收到的确认M1是对时间点2中重传M1的确认,则当前RTT的计算必须从时间点2开始计算。如果确认M1是对时间点1的M1的确认,那么当前RTT的计算必须从时间点1开始计算。
对于上面的这种情况,tcp使用了karn算法解决了这种模糊的情况,karn的算法在计算新的RTT时,如果重传了报文,则不会使用新的RTT值,反之,没有重传就更新RTT值。
7. 指数退避
对于上面Karn算法所描述的情况,如果发生了重传,那么RTO的数值又是多少?
此时tcp会采取指数退避策略,每一次重传,RTO的数值就会加倍。因此,如果报文重传一次,就是 2×RTO 2 × R T O ,如果重传了二次,就是 4×RTO 4 × R T O ,以此类推。

图5-指数退避
如上图所示:发送方发送了M1,经过3.24秒后,超时计时器超时并对M1进行了重传,而超时计时器重启设置为6.48秒,是原来RTO的2倍。发送方在超时时间内接收到了确认M1报文,此时RTO不变,重启超时计时器。接着发送方又发送了M2报文,在超时时间内收到了M2确认报文,然后才能重新计算RTO的数值(Karn算法)。
测量RTT新样本 = 2.15s,在这里我们假设之前的旧 RTTS R T T S = 1.625 ,旧 RTTD R T T D = 0.78,那么根据公式计算,这些变量的值为:
RTTS=(7/8)×1.625+(1/8)×2.15=1.690625 R T T S = ( 7 / 8 ) × 1.625 + ( 1 / 8 ) × 2.15 = 1.690625
RTTD=(3/4)×0.78+(1/4)×|1.690625−2.15|=0.69984375 R T T D = ( 3 / 4 ) × 0.78 + ( 1 / 4 ) × | 1.690625 − 2.15 | = 0.69984375
RTO=1.690625+4×0.69984375=4.49 R T O = 1.690625 + 4 × 0.69984375 = 4.49
说明: 这一篇比较偏理论,有一些公式需要计算,大家在看的时候发现有计算错误地方还请及时指出,感谢。