TCP的拥塞控制算法乍一看蛮简单的,最近复习的时候,却发现了两张相悖的图。暂时无法辨别。特此把资料记录一下,留待以后确认。
首先给出链接RFC-wiki:
不想看英文的观众可以看看这个:
这是小林coding V3.0中给出的cwnd变化图:
这是一张流传很广的图,也是我最初学习的版本。
这是RFC-wiki的快速恢复流程,详见上文链接。
- When the third duplicate ACK is received, set ssthresh to no more
than the value given in equation 3.
- Retransmit the lost segment and set cwnd to ssthresh plus 3*SMSS.
This artificially "inflates" the congestion window by the number
of segments (three) that have left the network and which the
receiver has buffered.
- For each additional duplicate ACK received, increment cwnd by
SMSS. This artificially inflates the congestion window in order
to reflect the additional segment that has left the network.
- Transmit a segment, if allowed by the new value of cwnd and the
receiver's advertised window.
- When the next ACK arrives that acknowledges new data, set cwnd to
ssthresh (the value set in step 1). This is termed "deflating"
the window.
也就是说,在三次收到重复ACK后,开启快速重传。
-
重设了ssthresh和cwnd。
-
cwnd确实先变为一半,紧接着加3(因为此时已经有3个包离开了网络到达了发送端)。
-
此时如果仍收到重复ACK,同理则cwnd持续加1。
如果收到新的ACK,则表示重传成功,将cwnd设为ssthresh并进入拥塞控制阶段。
个人认为
一般来说,重传应该在一个RTT中成功,cwnd先变为一半,再加3,和加1之后。在下一个RTT时应变回原来的一半。
即,发生快速重传前为12,一个RTT的过程中,cwnd的变化为:
12 -> 6 -> 9 -> 若干 +1 ->6
也就是说,虽然Reno算法在重传过程中变化了不少,但是cwnd应当在下一个RRT时变为一半,并进入拥塞避免。即第二张图片正确。
如果超过一个RTT重传仍不成功,即未收到新的ACK,可能收到或多次收到重复的ACK。 由于RTO应略大于RTT,不再收到ACK必定触发超时重传和慢启动,不会出现图一的情况。 仍受到重复的ACK,此时不会退出快速恢复算法,cwnd窗口持续加1,不会进入拥塞避免,也就不会出现图一的情况。
更新
小林老师回复了我的问题,最新的版本已经更新在他的网站上。 所以上面的分析基本是吻合的,但是轮次的地方依然有点疑问,附上最新的图片和网址。
在我的理解中,TCP窗口中的所有包,应该在一个轮次中发出,这样可以保证窗口的持续前进。所以触发重传后,当收到新的确认前,窗口会被卡在未被确认的位置,发送窗口中相距最远的数据包也不该在3个轮次后才返回造成重复确认,所以快速恢复 cwnd 的 “+ 1 过程” 画成直线是不严谨的。所以图中,快速恢复阶段,每个轮次CWND增长1,我不是很认同,个人认为,快速回复在一个轮次中完成可能更加符合实际。也就是: