快速重传算法在以前的文章中有介绍,若是收到一个out-of-order的报文段时, TCP须要马上产生一个ACK,这个ACK不该该被延时,目的在于让对方知道收到一个失序的报文,并告诉对方本身但愿收到的报文seq,咱们不知道这个重复的ACK的缘由,由于仍是会等待少许的重复ACK到来,若是连续收到3个或者3个以上的dup ACK,就被判断这个报文被丢失了,因而就须要当即重传丢失的数据段,这个地方不用等待定时器溢出。更详细的介绍能够参考:TCP-IP详解:超时重传机制html
TCP Reno这个算法定义在RFC5681。快速重传和快速恢复算法通常同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,因此没有必要像RTO超时那么强烈,并不须要从新回到慢启动进行,这样可能下降效率。因此协议栈会作以下工做算法
1. cwnd = cwnd/2 网络
2. sshthresh = cwnd ssh
而后启动快速恢复算法:ide
1. 设置cwnd = ssthresh+ACK个数*MSS(通常状况下会是3个dup ACK)性能
2. 重传丢失的数据包(对于重传丢失的那个数据包,能够参考TCP-IP详解:SACK选项)spa
3. 若是只收到Dup ACK,那么cwnd = cwnd + 1, 而且在容许的条件下发送一个报文段.net
4. 若是收到新的ACK, 设置cwnd = ssthresh, 进入拥塞避免阶段3d
其实TCP Reno算法就是在慢启动和拥塞避免的基础上增长了快速重传和快速恢复算法,避免了在拥塞不严重的情况下,过大的减少拥塞窗口,下降TCP的传输效率,这个算法的示意图以下,能够看到cwnd在遇到3个dup ACK的时候 cwnd减半,进入快速恢复模式.htm
这个算法存在的一个问题是,多个报文同时丢失的状况下会出现性能问题,系统会屡次执行快速重传和快速恢复算法,屡次下降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又要减半进入快速恢复阶段....