在網絡實際的傳輸過程中,會出現擁塞的現象,網絡上充斥着非常多的數據包,但是卻不能按時被傳送,形成網絡擁塞,其實就是和平時的堵車一個性質了。TCP設計中也考慮到這一點,使用了一些算法來檢測網絡擁塞現象,如果擁塞產生,變會調整發送策略,減少數據包的發送來緩解網絡的壓力。
擁塞控制主要有四個算法:
1. 慢啓動
2. 擁塞避免
3. 擁塞發生時,快速重傳
4. 快速恢復
慢啓動算法
之前介紹的滑動窗口能夠讓協議棧同時發送多個報文段,這樣可以提高網絡通信的效率,對於一些處理能力不佳的中間路由器,很可能會導致存儲被耗盡的狀況,從而嚴重降低了TCP連接的吞吐量,不斷的重傳. 非常的可怕, 介於此,引入了慢啓動這個算法。
慢啓動爲發送方的TCP增加了一個窗口:擁塞窗口,記爲cwnd,,初始化之後慢慢增加這個cwnd的值來提升速度。同時也引入了ssthresh門限值,如果cwnd達到這個值會讓cwnd的增長變得平滑,算法如下
1. 連接建好的開始先初始化cwnd = 1,表明可以傳一個MSS大小的數據
2. 每當收到一個ACK,cwnd++; 呈線性上升
3. 每當過了一個RTT,cwnd = cwnd*2; 呈指數讓升
4. 當cwnd >= ssthresh時,就會進入“擁塞避免算法”
擁塞避免算法
算法:
1)收到一個ACK時,cwnd = cwnd + 1/cwnd
2)當每過一個RTT時,cwnd = cwnd + 1
圖示
結合圖來看下數據發送過程中慢啓動和擁塞避免算法的使用情況
1. 連接建立,開始傳輸數據,cwnd = 1 , ssthresh的初始值爲16,發送第一個包
2. 發送端收到一個確認後,cwnd加1,於是可以 發送2個數據包
3. 收到2個ACK之後,這個時候cwnd + 2 , 於是可以發送4個數據包
4. 收到4個ACK後,這個時候cwnd + 4 ,於是可以發送8個數據包, 可以看到這個時間段,cwnd隨着傳輸輪次的增長,成指數增長
5. 當擁塞的窗口達到ssthresh後,慢啓動算法結束,開始進入擁塞避免算法
6. cwnd按照一個RTT進行+1的線性增加,假設到達24時,出現網絡擁塞
7. ssthresh = 1/2 * cwnd = 12, cwnd = 1 繼續重新執行慢啓動算法
8. 同樣當cwnd = 12時 執行擁塞避免算法
其中第7步屬於對網絡擁塞的一種處理, 什麼狀態下才會認爲是擁塞? 基本上就認爲是有丟包產生,在前面知道丟包產生會有2中處理方法超時重傳和快速重傳,其中如果RTO超時的時候,TCP認爲環境已經很糟糕了,
a .sshthresh = cwnd /2
b. cwnd 重置爲 1
c.進入慢啓動過程
如果是快速重傳,則:
TCP Tahoe的實現和RTO超時一樣。
TCP Reno的實現是:
a. cwnd = cwnd /2
b. sshthresh = cwnd
c. 進入快速恢復算法——Fast Recovery【下一篇文章介紹】
簡單的來說,發送的速率總是在不斷的增長,只不過一開始增長比較快,指數增長,到達門限值的時候,切換增長模式,變成線性增長,當系統中出現了丟包重傳現象,判斷已經網絡已經發送阻塞,要重新設定參數,進入慢啓動狀態。