TCP擁塞機制


 

原文:【圖解】你還在為 TCP 重傳、滑動窗口、流量控制、擁塞控制發愁嗎?看完圖解就不愁了

作者:小林coding 

擁塞控制

為什么要有擁塞控制呀,不是有流量控制了嗎?

前面的流量控制是避免「發送方」的數據填滿「接收方」的緩存,但是並不知道網絡的中發生了什么。

一般來說,計算機網絡都處在一個共享的環境。因此也有可能會因為其他主機之間的通信使得網絡擁堵。

在網絡出現擁堵時,如果繼續發送大量數據包,可能會導致數據包時延、丟失等,這時 TCP 就會重傳數據,但是一重傳就會導致網絡的負擔更重,於是會導致更大的延遲以及更多的丟包,這個情況就會進入惡性循環被不斷地放大….

所以,TCP 不能忽略網絡上發生的事,它被設計成一個無私的協議,當網絡發送擁塞時,TCP 會自我犧牲,降低發送的數據量。

於是,就有了擁塞控制,控制的目的就是避免「發送方」的數據填滿整個網絡。

為了在「發送方」調節所要發送數據的量,定義了一個叫做「擁塞窗口」的概念。

什么是擁塞窗口?和發送窗口有什么關系呢?

擁塞窗口 cwnd是發送方維護的一個 的狀態變量,它會根據網絡的擁塞程度動態變化的

我們在前面提到過發送窗口 swnd 和接收窗口 rwnd 是約等於的關系,那么由於入了擁塞窗口的概念后,此時發送窗口的值是swnd = min(cwnd, rwnd),也就是擁塞窗口和接收窗口中的最小值。

擁塞窗口 cwnd 變化的規則:

  • 只要網絡中沒有出現擁塞,cwnd 就會增大;
  • 但網絡中出現了擁塞,cwnd 就減少;

那么怎么知道當前網絡是否出現了擁塞呢?

其實只要「發送方」沒有在規定時間內接收到 ACK 應答報文,也就是發生了超時重傳,就會認為網絡出現了用擁塞。

擁塞控制有哪些控制算法?

擁塞控制主要是四個算法:

  • 慢啟動
  • 擁塞避免
  • 擁塞發生
  • 快速恢復

慢啟動

TCP 在剛建立連接完成后,首先是有個慢啟動的過程,這個慢啟動的意思就是一點一點的提高發送數據包的數量,如果一上來就發大量的數據,這不是給網絡添堵嗎?

慢啟動的算法記住一個規則就行:當發送方每收到一個 ACK,就擁塞窗口 cwnd 的大小就會加 1。

這里假定擁塞窗口 cwnd 和發送窗口 swnd 相等,下面舉個栗子:

  • 連接建立完成后,一開始初始化 cwnd = 1,表示可以傳一個 MSS 大小的數據。
  • 當收到一個 ACK 確認應答后,cwnd 增加 1,於是一次能夠發送 2 個
  • 當收到 2 個的 ACK 確認應答后, cwnd 增加 2,於是就可以比之前多發2 個,所以這一次能夠發送 4 個
  • 當這 4 個的 ACK 確認到來的時候,每個確認 cwnd 增加 1, 4 個確認 cwnd 增加 4,於是就可以比之前多發 4 個,所以這一次能夠發送 8 個。

可以看出慢啟動算法,發包的個數是指數性的增長

那慢啟動漲到什么時候是個頭呢?

有一個叫慢啟動門限 ssthresh (slow start threshold)狀態變量。

  • 當 cwnd < ssthresh 時,使用慢啟動算法。
  • 當 cwnd >= ssthresh 時,就會使用「擁塞避免算法」。

擁塞避免算法

前面說道,當擁塞窗口 cwnd 「超過」慢啟動門限 ssthresh 就會進入擁塞避免算法。

一般來說 ssthresh 的大小是 65535 字節。

那么進入擁塞避免算法后,它的規則是:每當收到一個 ACK 時,cwnd 增加 1/cwnd。

接上前面的慢啟動的栗子,現假定 ssthresh 為 8

  • 當 8 個 ACK 應答確認到來時,每個確認增加 1/8,8 個 ACK 確認 cwnd 一共增加 1,於是這一次能夠發送 9 個 MSS 大小的數據,變成了線性增長。

所以,我們可以發現,擁塞避免算法就是將原本慢啟動算法的指數增長變成了線性增長,還是增長階段,但是增長速度緩慢了一些。

就這么一直增長着后,網絡就會慢慢進入了擁塞的狀況了,於是就會出現丟包現象,這時就需要對丟失的數據包進行重傳。

當觸發了重傳機制,也就進入了「擁塞發生算法」。

擁塞發生

當網絡出現擁塞,也就是會發生數據包重傳,重傳機制主要有兩種:

  • 超時重傳
  • 快速重傳

這兩種使用的擁塞發送算法是不同的,接下來分別來說說。

發生超時重傳的擁塞發生算法

當發生了「超時重傳」,則就會使用擁塞發生算法。

這個時候,sshresh 和 cwnd 的值會發生變化:

  • ssthresh 設為 cwnd/2
  • cwnd 重置為 1

接着,就重新開始慢啟動,慢啟動是會突然減少數據流的。這真是一旦「超時重傳」,馬上回到解放前。但是這種方式太激進了,反應也很強烈,會造成網絡卡頓。

就好像本來在秋名山高速漂移着,突然來個緊急剎車,輪胎受得了嗎。。。

發生快速重傳的擁塞發生算法

還有更好的方式,前面我們講過「快速重傳算法」。當接收方發現丟了一個中間包的時候,發送三次前一個包的 ACK,於是發送端就會快速地重傳,不必等待超時再重傳。

TCP 認為這種情況不嚴重,因為大部分沒丟,只丟了一小部分,則 ssthresh 和 cwnd 變化如下:

  • cwnd = cwnd/2 ,也就是設置為原來的一半;
  • ssthresh = cwnd;
  • 進入快速恢復算法

快速恢復

快速重傳和快速恢復算法一般同時使用,快速恢復算法是認為,你還能收到 3 個重復 ACK 說明網絡也不那么糟糕,所以沒有必要像 RTO 超時那么強烈。

正如前面所說,進入快速恢復之前,cwnd 和 ssthresh 已被更新了:

  • cwnd = cwnd/2 ,也就是設置為原來的一半;
  • ssthresh = cwnd;

然后,進入快速恢復算法如下:

  • 擁塞窗口 cwnd = ssthresh + 3 ( 3 的意思是確認有 3 個數據包被收到了)
  • 重傳丟失的數據包
  • 如果再收到重復的 ACK,那么 cwnd 增加 1
  • 如果收到新數據的 ACK 后,設置 cwnd 為 ssthresh,接着就進入了擁塞避免算法

也就是沒有像「超時重傳」一夜回到解放前,而是還在比較高的值,后續呈線性增長。

擁塞算法示意圖

好了,以上就是擁塞控制的全部內容了,看完后,你再來看下面這張圖片,每個過程我相信你都能明白:

TCP 擁塞控制

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM