TCP的超时与重传

来源:互联网 发布:linux驱动模块编译 编辑:程序博客网 时间:2024/06/04 18:31

1. 背景与原理

超时重传是TCP协议保证数据可靠性的一个重要机制,其原理是在发送某一个数据之后就开启一个计时器,在一定时间内如果没有得到发送的数据包的ACK报文,那么就重新发送数据,直到发送成功为止。


2. 往返时延的估计和超时

超时间隔长度的设计是超时/重传机制的核心部分,显然,超时间隔必须大于TCP连接的往返时延(RTT),即从一个报文段发出到收到其确认时。超时时间过长会造成网络利用率不高,过短会造成多次重传,使得网络阻塞。

2.1 估计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

2.2 设置和管理重传超时间隔

假设已经得到EstimatedRTT和DevRTT值,TCP超时间隔应该怎么设置?很显然,超时间隔应该大于等于EstimatedRTT,否则将造成不必要的重传。但是超时间隔也不应该比EstimatedRTT大太多,否则当报文段丢失时,TCP不能很快地重传报文段,从而将给上层应用带来很大的数据传输时延。因此,要求将超时间隔设置为EstimatedRTT加上一定余量。当SampleRTT值波动大时,这个余量应该大些,反之,则小。一般使用下面的公式去更新:
TimeoutInterval (RTO) = EstimatedRTT+4*DevRTT


3. 快速重传

超时触发重传的一个问题是超时周期可能相对较长,那么当一个报文段丢失时,这种长超时周期迫使发送方等待很长时间才重传丢失的分组,因而增加了端到端的时延。故如果在发生数据丢包的情况下,如果TCP发送方接收到对相同数据的3个冗余的ACK,它就认为跟在这个已被确认过3次的报文段之后的报文段已经丢失。一旦收到3个冗余的ACK,TCP就执行快速重传,即在其定时器过期之前重传该报文段。

这里写图片描述


4. TCP拥塞控制

4.1 流量控制与拥塞控制

流量控制是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读速率的匹配。而拥塞控制是因IP网络的拥塞而遏制发送方的速率。TCP通过让发送方维护一个接收窗口(RcvWindow)的变量来提供流量控制,即接收窗口告诉发送方,该接收方还有多少可用的缓存空间。

这里写图片描述

这里需要注意的是,当接收方的接收窗口为0时,即接收缓存已经存满,发送方继续发送确认报文,最后接收方缓存将开始清空,并且确认报文里将包含一个非0的RcvWindow值。

TCP拥塞控制机制让连接的每一段都记录一个额外的变量,即拥塞窗口(CongWin),它对一个TCP发送方能向网络发送流量的速率进行了限制。

4.2 拥塞控制算法

4.2.1 加性增,乘性减
  • 加性增,即当TCP发送方察觉到网络无拥塞时,采取的增大发送速率的策略,一般是每次它收到一个确认后就把CongWin增加一点,其目标是在每个RTT内CongWin增加一个MSS.
  • 乘性减,即当TCP发送方察觉到网络拥塞时,采取降低发送速率的策略,每发生一次丢包事件就将当前的CongWin减半。

这里写图片描述

4.2.1 慢启动

TCP发送方在初始阶段不是线性增加其发送速率,而是以指数速度增加,每过一个RTT将CongWin值翻倍。TCP发送方继续以指数速度增加其发送速率,直到发生一个丢包事件为止,此时CongWin将被降为一半,然后线性增长。

这里写图片描述

何时结束指数增长?
1. 如果存在一个由超时指示的丢包事件(拥塞),TCP发送方将拥塞窗口(cwnd)设为1并重新开始慢启动过程。并且它将第二个状态变量的值ssthresh (慢启动阈值)设置为cwnd/2,即当检测到拥塞时将ssthresh设置为拥塞窗口值的1/2;
2. 当cwnd的值等于ssthresh时,结束慢启动并且TCP转移到拥塞避免模式。
3. 如果检测到3个冗余的ACK,TCP执行快速重传,并进入快速恢复状态。

快速恢复算法:

  1. 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍报文段的大小。
  2. 每次收到另一个重复的ACK,cwnd增加1个报文段大小并发送1个分组
  3. 当下一个确认新数据的ACK到达时,设置cwnd为ssthresh。

下图中TCP Reno算法就综合了快速恢复算法。当丢包事件发生时(收到3个重复的ACK),拥塞窗口的值为12MSS,那么cwnd设置为3+12/2=9MSS,结束慢启动阶段,进入拥塞避免阶段,线性增长cwnd。

这里写图片描述


另外注意的两点:

1. 当给定连接返回ICMP差错时,TCP会忽略ICMP的差错并坚持重传。

2. 当TCP超时并重传是,它不一定要重传同样的报文段,相反,TCP允许进行重新分组而发送一个较大的报文段,这样有助于提高性能。

原创粉丝点击