名詞解釋:
cwnd -- 擁塞窗口
ssthresh(slow start threshold)-- 慢啟動到擁塞避免到閾值
RTT——Round Trip Time,也就是一個數據包從發出去到回來的時間
RTO(Retransmission TimeOut)重發超時時間
為什么有了滑動窗口還需要有擁塞窗口?
滑動窗口是對發送接收雙方的流量控制,如果中間的網絡設備的轉發性能達到極限是無法感知到的,而tcp除了針對自身的收發能力做調整,還根據整體的網絡情況做調整,所以有了擁塞窗口。
擁塞控制分為四個階段,每個階段的處理策略都不同,大概就是先猛增,然后小心增長預防擁塞,還有就是已經發生擁塞了的措施和快速恢復。
慢啟動
此階段的操作:
cwnd設置為一個很小的初始值,這個初始值在不同版本里面是不一樣的,有1、3、10等。
每收到一個ack,cwnd = cwnd+1
cwnd*2
cwnd成指數級別遞增。
跳出該階段的標志:cwnd等於ssthresh時,進入擁塞避免階段,那么ssthresh的值該設置成多少?將在后面介紹。
擁塞避免
此階段的操作:
收到一個ACK時,cwnd = cwnd + 1/cwnd
當每過一個RTT時,cwnd = cwnd + 1
此階段cwnd成線性增長。
跳出該階段的標志:發生擁塞,此時進入發生擁塞階段
發生擁塞
分為兩種情況:
1)RTO超時,重傳數據包。TCP認為這種情況網絡上很糟糕了,反應也很強烈。
sshthresh = cwnd /2
cwnd 重置為初始值
進入慢啟動過程
2)收到3個duplicate ACK,這種情況認為網絡情況還可以,反應不是很強烈。
cwnd = cwnd /2
sshthresh = cwnd
進入快速恢復階段
跳出該階段的標志:出現一下,處理之后必然跳出到其他狀態。
為什么快速恢復中會收到多個相同的ack,以及為什么認為收到多個相同ack要比RTO的網絡情況好? 將在后面介紹。
快速恢復
cwnd = sshthresh + 3 * MSS (3的意思是確認有3個數據包被收到了)
重傳Duplicated ACKs指定的數據包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就進入了擁塞避免的算法了
跳出該階段的標志:出現一下,處理之后必然跳出到其他狀態。
ssthresh的值該設置成多少?
動態的,因為不同設備,不同網絡環境中網絡等承載能力是不同的,初始值會設置很大,
#define TCP_INFINITE_SSTHRESH 0x7fffffff,然后按照上面介紹的到了擁塞發生階段,sshthresh會被設置成擁塞發生時候,擁塞窗口的一半。
#define TCP_INFINITE_SSTHRESH 0x7fffffff,然后按照上面介紹的到了擁塞發生階段,sshthresh會被設置成擁塞發生時候,擁塞窗口的一半。
為什么快速恢復中會收到多個相同的ack,以及為什么認為收到多個相同ack要比RTO的網絡情況好?
這個是tcp的快速重傳機制,接收方如果收到的包不連續,從斷點開始,每次收到新包,都ack丟失點的序號,如果發送方連續收到3次相同的ack,就重傳。Fast Retransmit的好處是不用等timeout了再重傳。舉例:如果發送方發出了1,2,3,4,5份數據,第一份先到送了,於是就ack回2,結果2因為某些原因沒收到,3到達了,於是還是ack回2,后面的4和5都到了,但是還是ack回2,因為2還是沒有收到,於是發送端收到了三個ack=2的確認,知道了2還沒有到,於是就馬上重轉2。然后,接收端收到了2,此時因為3,4,5都收到了,於是ack回6。從上面也能看出收到三個相同的2的ack,起碼說明網絡中還能正常來回傳輸3,4,5等,說明網絡還有的救,所以反應沒那么激烈,而RTO說明這段時間不僅僅是2丟了,而且2丟了這段時間還沒有收到后面的3個包,所以tcp就認為網絡比較糟糕了,反應也比較激烈。