TCP-IP详解:快速重传与快速恢复

时间:2022-07-02 10:26:46

快速重传算法

快速重传算法在之前的文章中有介绍,如果收到一个out-of-order的报文段时, TCP需要立刻产生一个ACK,这个ACK不应该被延时,目的在于让对方知道收到一个失序的报文,并告诉对方自己希望收到的报文seq,我们不知道这个重复的ACK的原因,因为还是会等待少量的重复ACK到来,如果连续收到3个或者3个以上的dup ACK,就被判断这个报文被丢失了,于是就需要立即重传丢失的数据段,这个地方不用等待定时器溢出。更详细的介绍可以参考:TCP-IP详解:超时重传机制


快速恢复算法

TCP Reno这个算法定义在RFC5681。快速重传和快速恢复算法一般同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈,并不需要重新回到慢启动进行,这样可能降低效率。所以协议栈会做如下工作

1.  cwnd = cwnd/2 

2. sshthresh = cwnd 

然后启动快速恢复算法:

1. 设置cwnd = ssthresh+ACK个数*MSS(一般情况下会是3个dup ACK)

2. 重传丢失的数据包(对于重传丢失的那个数据包,可以参考TCP-IP详解:SACK选项

3. 如果只收到Dup ACK,那么cwnd = cwnd + 1, 并且在允许的条件下发送一个报文段

4. 如果收到新的ACK, 设置cwnd = ssthresh, 进入拥塞避免阶段


TCP Reno算法

其实TCP Reno算法就是在慢启动和拥塞避免的基础上增加了快速重传和快速恢复算法,避免了在拥塞不严重的状况下,过大的减小拥塞窗口,降低TCP的传输效率,这个算法的示意图如下,可以看到cwnd在遇到3个dup ACK的时候 cwnd减半,进入快速恢复模式.

TCP-IP详解:快速重传与快速恢复

这个算法存在的一个问题是,多个报文同时丢失的情况下会出现性能问题,系统会多次执行快速重传和快速恢复算法,多次降低cwnd的值,降低了传输的效率。

可以看下Reno丢失2个包的状况了
1. cwnd = 10 

2. 发送数据包,但是3包和6包丢失

3. 收到数据包1的ACK, cwnd = 11

4. 收到数据包2的ACK,  cwnd = 11

5. 收到数据包2的Dup ACK,cwnd = 11

6. 收到数据包2的Dup ACK, cwnd = 11

7. 收到数据包2的dup ACK, cwnd = 11 , 3个dup ACK,启动快速重传算法,立即发送数据包3,然后进入快速恢复阶段

8. ssh = 11/2 = 5  cwnd = 5+3 = 8

9. 收到一个dup ACK cwnd + 1  直到收到一个新的ACK,cwnd = ssh = 5  进入拥塞避免阶段

10. 可是又连续收到dup ACK,进行快速重传,cwnd又要减半进入快速恢复阶段.... 


TCP-IP详解:快速重传与快速恢复

TCP New Reno

这个算法是Reno算法的改进,没有使用SACK机制
  • 当sender这边收到了3个Duplicated Acks,进入Fast Retransimit模式,开始重传重复Acks指示的那个包。如果只有这一个包丢了,那么,重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。如果没有的话,说明有多个包丢了。我们叫这个ACK为Partial ACK。
  • 一旦Sender这边发现了Partial ACK出现,那么sender就可以推理出来有多个包被丢了,于是乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack,才真正结束Fast Recovery这个过程