注意,注意,注意:
1、这是我2018找实习、找工作的总结,是在网上结合很多别人总结文章自己再东拼西凑的,如有错误请大家指出,我再去找资料补充。
2、很多内容来自别人博主,十分感谢,当时摘抄实在太匆忙,有的忘了出处,如有冒犯,侵删。
3、祝各位很闲也有钱。
往返时延的估计和超时
超时间隔长度的设计是超时/重传机制的核心部分,显然,超时间隔必须大于TCP连接的往返时延(RTT),即从一个报文段发出到收到其确认时。超时时间过长会造成网络利用率不高,过短会造成多次重传,使得网络阻塞。
估计RTT
报文段的样本RTT(SampleRTT)就是从某报文段被发出到对该报文段的确认被收到之间的时间值。大多数TCP的实现仅在某个时刻做一次SampleRTT的测量,而不是为每个发送的报文段测量一个SampleRTT 。TCP维持一个SampleRTT均值(EstimatedRTT) 一旦获得一个新的SampleRTT, TCP会根据下面的公式更新EstimatedRTT
EstimatedRTT=(1-a)*EstimatedRTT+a *SampleRTT
a的值一般为0.125。
除了估算RTT外,测量RTT的变化也是有意义的。我们定义DevRTT,用于估算SampleRTT 偏离EstimatedRTT的程度:
DevRTT=(1-b) * DevRTT+b * |SampleRTT-EstimatedRTT|
b的值一般为0.25
设置和管理重传超时间隔
假设已经得到EstimatedRTT和DevRTT值,TCP超时间隔应该怎么设置?
很显然,超时间隔应该大于等于EstimatedRTT,否则将造成不必要的重传。但是超时间隔也不应该比EstimatedRTT大太多,否则当报文段丢失时,TCP不能很快地重传报文段,从而将给上层应用带来很大的数据传输时延。因此,要求将超时间隔设置为EstimatedRTT加上一定余量。当SampleRTT值波动大时,这个余量应该大些,反之,则小。一般使用下面的公式去更新:
TimeoutInterval (RTO) = EstimatedRTT+4*DevRTT
往返时间(RTT)
超时重传时间(Retransmission TimeOut, RTO)要怎么设置呢?
数据包过去,到 ack 返回,这个时间一般约等于 RTT 时间,如果一个 RTT 时间内没有收到 ack,很可能对方就没有收到数据,或者回送的 ack 丢失。
所以,最直观的想法是,RTO 应该比 RTT 稍稍大一点。
比如:
RTO=RTT+Δt
当然,这只是我们自己臆想的公式,说不定,TCP 一开始创造出来的时候,RTO 真的是这么算的呢?
RTT 测量
可是,在公式中,RTT 是如何测量呢?在 TCP 中,每一次数据包传送过去到接收到对方的 ack 这个时间差,就会被 TCP 记录,然后保存到一个变量 RTTs 中去。
在局域网中,我们的网络一般是很稳定的,每次重新计算一个 RTT,基本上变化不太大,但是在广域网中,网络就会变得异常复杂,这一次的 RTT 为 100ms,说不定下一次就变 800 ms 了,这时候,采用实时计算的 RTT 就会不合理,在 RFC 中,使用了加权的 RTT。它的公式如下:
RTTs=(1−α)×RTTs+α×RTTnew
RFC 2988 建议 α=0.125。上面这个公式说明,我想使用旧的 RTTs 中的 87.5% 的成分,新的 RTT 样本中 12.5% 的成分,这样就不至于让加权的 RTTs 发生剧烈抖动。一个直观的例子就是,某些同学的成绩太差,拉低了班级的整体水平,为了防止这种现象,可以在计算平均值的时候动些手脚。
举个例子,当前 RTTs=200ms,最新一次测量的 RTT=800ms,那么更新后的 RTTs=200×0.875+800×0.125=275ms.
Δt 怎么定义
在前面,我们臆想了一个公式:
RTO=RTT+Δt
现在我们将其更新为
RTO=RTTs+Δt
RTTS 的计算方法我们在 2.1 中已经介绍过了,现在是 Δt 是什么,它怎么算?我们只知道,它应该很小。RFC 2988 规定:
RTO=RTTs+4×RTTD
因此,按照上面的定义,Δt=4×RTTD. 而 RTTD 计算公式如下:
RTTD=(1−β)×RTTD+β×|RTTs−RTT|
实际上,RTTD 就是一个均值偏差,它就相当于某个样本到其总体平均值的距离。这就好比你的成绩与你班级平均成绩差了多少。
RFC 推荐 β=0.25.
指数退避
假设在某一次发送数据的时候,数据丢失了,根据前面的公式,我们计算出了一个 RTO 值。如果和重传后,还是没有等到对方的 ack,那么 RTO 的值就会翻倍。只要重传的的数据没有 ack,那么 RTO 就会一直翻倍。
则第 n 次重传的 RTOn 值为:
RTOn=2n−1×RTO1
Karn 算法
假设一个分组被发送,经过若干次和重传后,收到了对方的 ack,则新的 RTT 如何计算呢?实际上,我们根本没有办法知道这个 ack 是对哪一次重传数据的确认,因此,Karn 算法规定:此时不更新 RTTs 的值。
如果下一次再发生重传,使用退避后的 RTO 的值。