准备工作:TCP接收端在收到数据的时候,会返回一个ACK信息,所以我们可以<br>在这个ACK信息中携带一个字节的数据来测量传输该确认信息所需要的时间。每<br>个测量结果称为RTT样本。然后TCP根据一段时间的RTT样本得到一个RTO估计值<br>那么如何根据RTT估计RTO呢?
经典方法
SRTT=aSRTT+(1-a)*RTT
SRTT为平滑RTT估计值,所以SRTT是基于当前值和新的样本值来更新的。a为平滑因子,推荐0.8~0.9<br>因此,根据a的设定值,新的估计值有80%~90%来自当前值,10%~20%来自新的样本值。<br>这种计算方法称为EWMA。考虑到SRTT估计器得到的估计值会随着RTT而变化。[RFC0793]根据以下公式设置RTO<br><br>
RTO=min(ubound,max(lbound,b*(SRTT)))
b:时延因子,推荐1.3~2.0<br>ubound:RTO的上边界,推荐1分钟<br>lbound:RTO下边界,推荐1S<br>该方法使得RTO设置为1S或者是2倍SRTT<br>称为经典方法
分析:若RTT相对稳定,则这种方法效果不错
若RTT波动较大,可以发现新的样本变化值如果变化较大的时候,如实际RTT远大于估计RTT,会引起不必要的重传。而增大的RTT样本已经表明了网络已经负载,若发生重传,则进一步加大了网络负担
因此可以考虑根据RTT测量值的变化情况和均值来得到较准确的估计值
标准方法
初始化值之后,按照下面方式进行估计:
strr=(1-g)strr+g(M)
rttvar=(1-h)rttvar+h(|M-srtt|)
RTO=srtt+4*rttvar
M为每个测量结果,strr为平均值的EWMA(经典方法中提到的计算方法),rttvar为平均偏差的EWMA
另外一种计算机方便实现的写法:
Err=M-strr
srtt=srtt+g(Err)
rttvar=rttvar+h(|Err|-rttvar)
RTO=srtt+4(rttvar)
Err为当前的测量值M与估计值srtt的误差,srtt为均值的EWMA,rttvar为绝对误差的EWMA,g为新RTT样本占SRTT估计值的比重,=1/8。h为新的平均偏差样本占偏差估计值的比重,=0.25
这种方法加入了对测量值和估计值之前的误差的考虑:M-srtt。且若误差越大,表明网络越来越差(或越好),则h(|M-srtt|)也越大,RTO中该项占的比重较大,所以影响大,能较快的提高RTO的值。而经典方法里面,测量值仅占0.1~0.2,改变速度太慢。
初始值
在首个SYN报文交换之前,TCP无法获取RTO的值,也就无法获取估计器的估计值。根据[RFC6298],RTO初始值为1S,初始SYN段的超时间隔为3S。收到首个RTT测量结果M之后,估计器按照以下方式初始化:srtt=M,rttvar=M/2
重传二义性与Karn算法
假设一个包的传输出现超时,该包会被重发,接着发送端收到一个确认信息,该信息是第一次的还是第二次的包的确认信号呢?
Karn算法第一部分指出:当出去重传超时时,接收到的确认信息不能用来更新RTT估计值。但是如果我们只是简单的忽略重传问题,就可能将网络中的有用信息也忽略了,即网络中可能存在一些因素影响了传输速度。这时候,如果在再次发生丢包前,降低重传率可以减少网络负担,也就是指数退避算法。
TCP在计算RTO时采用一个退避系数,每当计时器出现超时,则退避系数加倍,直到接收到非重传数据,此时系数设置为1。仅当接收到未重传的数据时,该SRTT才用于计算RTO.