TCP Reno引入了ssthresh(Slow Start threshold)变量,做为TCP的Slow Start和Congestion Avoidance两个阶段的分界线。算法
当cwnd < ssthresh时,TCP保持在Slow Start阶段;网络
当cwnd >= ssthresh时,TCP进入Congestion Avoidance阶段。性能
ssthresh实际上影响着TCP的性能,但其初始值在RFC中没有明肯定义,能够为任意大的值,在实现时通常初始化为rwnd。spa
TCP Reno拥塞控制算法继承了“数据包守恒准则”,保证处于网络中的packet的总量是守恒的。它经过4个算法保证这一点:继承
1. Slow Startit
在TCP链接创建以后,因为不知道实际可用的网络带宽,所以采用Slow Start算法,当心翼翼地对网络状况进行探测。io
进入Slow Start阶段,首先设置cwnd=1,接着cwnd会随着时间的推动呈指数级增长(所以,其过程并不slow)。具体作法是每收到一个ACK,就对cwnd+1,这样至关于每通过一个RTT,cwnd就翻一番。ast
在遇到两种状况时,Slow Start阶段会截止:class
(1)当cwnd达到ssthresh时,此时TCP会进入Congestion Avoidance阶段。效率
(2)当拥塞发生时,此时又分两种状况:
(2.1)若是是超时,会重传未被响应的packet,并将ssthresh设置为cwnd/2,并将cwnd重置为1,而后从新进入Slow Start阶段。
(2.2)若是是3个重复ACK,会先进行Fast Retransmit,而后进入Fast Recovery阶段。
2. Congestion Avoidance
在该阶段,cwnd再也不像Slow Start那样指数级增加,而是线性增加。具体作法是每收到一个ACK,就对cwnd+1/cwnd,这样至关于每过一个RTT,cwnd都加1。
当拥塞发生时,Congestion Avoidance阶段即截止,接下来的过程与Slow Start处理拥塞的方式相同:
(1)若是是超时,会重传未被响应的packet,并将ssthresh设置为cwnd/2,并将cwnd重置为1,而后进入Slow Start阶段。
(2)若是是3个重复ACK,会先进行Fast Retransmit,最后进入Fast Recovery阶段。
3. Fast Retransmit
当检测是否丢包时,每次都要等待超时的发生,会浪费很长时间,所以引入了Fast Retransmit机制。
经过TCP的机制可知,sender只要收到3个重复ACK,即认为丢包发生,此时会当即重传丢失的包,而再也不等待超时的出现。
4. Fast Recovery
为了解决丢包后进入Slow Start引发的效率下降,在Fast Retransmit的基础上,又引入了Fast Recovery机制。
该阶段首先将ssthresh设置为cwnd/2,而后重传丢失的包,再对cwnd进行充气(而不是SlowStart那样将cwnd重置为1),具体作法是在cwnd=ssthresh+3(用以反映3个packet正常离开了network)。
以后,每当再次收到一个重复ACK时,sender都会对cwnd+1,这是为了反映一个packet正常离开了network。
这里可能有两个疑问:
(1)怎么得知一个packet正常离开了network呢?这是由于receiver只有在收到packet以后,才会回复ACK,既然sender收到了ACK,说明有一个packet被receiver接收,即正常离开了network。
(2)那么,为何须要对cwnd+1呢?这是由于一个packet离开了network,使得network再也不饱和,为了使network从新平衡,须要发送新的packet到network中,这就必须经过增大cwnd来实现。
随着cwnd的增大,会将新进入窗口的packet发送出去。这个过程称为inflating。
直到收到新的ACK以后,inflating截止,进入deflating过程。所谓deflating,即将cwnd设置为ssthresh。
为何收到新的ACK后,须要进行deflating呢?这是由于,新的ACK意味着,刚进入Fast Recovery时重传的packet已经被接收,该ACK便是receiver对重传packet的回应。能够认为lost packet已经恢复了,能够结束Fast Recovery阶段。
值得注意的是,该ACK可能一次性响应了多个连续的packet。这是由于,从lost packet发生时起,到lost packet恢复为止,期间sender发送了多个后续packet,所以在receiver回复ACK时,会指明已接收到的最末端的packet的sequence number。