由于下层网络层(IP)可能出现丢失、重复或失序包的情况,TCP 协议提供可靠数据传输服务。为保证数据传输的正确性,TCP 重传其认为已经丢失的包。TCP 有两套重传机制,一是基于定时器(超时),二是基于确认信息的构成(快速重传)。
基于计时器的重传
TCP在发送数据时会设置一个计时器,若至计时器超时仍未收到数据确认信息(ACK),则会引发相应的超时或基于计时器的重传操作,计时器超时称为重传超时(Retansmission Timeouts,RTO)。
图中黑色那条就是因为定时器超时仍没有收到 ACK,所以引起了发送方超时重传。
实际上, TCP 有两个阈值来决定如何重传同一个报文段:一是愿意重传的次数 R1、二是应该放弃当前连接的时机 R2。R1 和 R2 的值应分别至少为 3 次和 100 秒,如果超过任何一个但还没能重传成功,会放弃该连接。当然这两个值是可以设置的,在不同系统里默认值也不同。
那么如何设定一个合适的超时的值呢?假设 TCP 工作在静态环境中,这很容易,但真实网络环境不断变化,需要根据当前状态来设定合适的值。
1、设置重传超时(RTO)
RTO(retransmission timeout)一般是根据RTT(round trip time)也就是往返时间来设置的。
若 RTO 小于 RTT,则会造成很多不必要的重传;
若 RTO 远大于 RTT,则会降低整体网络利用率,RTO 是保证 TCP 性能的关键。并且不同连接的RTT不相同,同一个连接不同时间的 RTT 也不相同,所以 RTO 的设置一直都是研究热点。
凭我们的直觉,RTO 应该比 RTT 稍大:
? RTO=RTT+Δt
那么,RTT 怎么算呢:
? SRTT=α(SRTT)+(1-α)RTTnew
SRTT(smooth RTT),RTTnew 是新测量的值。如上,为了防止 RTT 抖动太大,给了一个权值 a ,也叫平滑因子。a 的值建议在 80%~90%。举个例子,当前 SRTT=200ms,最新一次测量的 RTTnew=800ms,那么更新后的 SRTT=200×0.875+800×0.125=275ms.
根据前面求的SRTT计算出RTO:
RTO = min(ubound, max(lbound, (SRTT)β))
β是时延离散因子,推荐值1.3~2.0。 ubound是RTO上边界,lbound是下边界。这种计算方法就是经典方法。它是的RTO值设置为1s或约两倍的SRTT。
这种方法缺点就是没法适应大规模的变动(网络不稳定情况)。
2、退避指数
根据前面的公式,我们可以得到 RTO。一旦超过 RTO 还没收到 ACK,就会引起发送方重传。但如果重传后还是没有在 RTO 时间内收到 ACK,这时候会认为是网络拥堵,会引发 TCP 拥塞控制行为,使 RTO 翻倍。则第 n 次重传的 RTOn 值为:
? RTOn=2^(n−1)×RTO1
下图是一个例子:
3、带时间戳的 RTT 测量
前面说了 RTO 的公式,它和 RTT 有关,那么每一次的 RTT 是如何得到的呢?
在之前 TCP 连接管理的时候讲过,TCP有一个 TSOPT (timestamp option) 选项,它包含两个时间戳值。它允许发送者在报文中带上一个32比特的时间戳值(TSV),然后接收方将收到的值原封不动的填入 ACK 报文段中 TSOPT 选项的第二部分,时间戳回显字段(TSER)。发送方收到 ACK 以后,将当前时间戳减去 TSOPT 选项的 TSER 就可得到精确的RTT值。
但是这里有很微妙的细节:接收方在收到数据包后,并不是立即发送 ACK,通常会延时“一小会儿”,多等待几个数据包后返回一个累积 ACK。此时接收方将确认时间最近的报文段的 TSV 填入 TSER 发送给发送方。
4、重传二义性与 Karn 算法
还有另一个重要的细节,如果测量 RTT 的样本出现了超时重传,导致我们收到 ACK 时无法分辨是对哪一次的确认,这时候 RTT 的值可能是不正确的。
因此,Karn 算法规定:此时不更新 RTTnew 的值。并且如果发生再次重传,则采用退避后的 RTO 的值,直到发送成功,退避指数重新设定为 1 。
基于确认信息的重传(快速重传)
在大多数情况下,计时器超时并触发重传是不必要的,也不是期望的,因为 RTO 通常是大于 RTT(约2倍或更大),因此基于计时器的重传会导致网络利用率降低。
快速重传机制基于接收端的反馈信息来引发重传,与超时重传相比,快速重传能更加及时有效的修复丢包情况。
首先我们要知道,接收方收到失序报文段时,应立即生成确认信息(重复 ACK),以便发送方尽快、高效地填补空缺。而发送方在收到重复 ACK 时,无法判断是由于数据包丢失还是仅仅因为延迟,所以发送方等待一定数目的重复 ACK (重复 ACK 阈值,dupthresh),这时可以认为是数据包丢失,即便还未超时,也立即发送丢失的分组。
所以快速重传概括如下:TCP 发送方在观测到至少 dupthresh ( 通常是 3 ) 个重复 ACK,立即重传,而不必得到计时器超时。当然也可以同时发送新的数据。
如下图所示:
原文地址:https://www.cnblogs.com/wang-shishuang/p/10678434.html