擁塞控制是TCP傳輸中很重要的一環,TCP擁塞控制使用一個擁塞窗口以及擁塞策略來進行擁塞控制。在前面的流量控制中提到發送端的發送窗口取決於接收窗口,實際上,發送方的窗口大小是接收窗口與擁塞窗口中的較小值。擁塞窗口的大小又取決於網絡的擁塞狀況。而具體確定擁塞窗口大小則需要擁塞策略來決定。

擁塞策略包括慢開始擁塞避免擁塞檢測。TCP的一般是從一個比較小的傳輸速率開始,然後迅速增大到閾值,到達閾值後以一個比較小的速率繼續傳輸,如果傳輸過程中遇到了網絡擁塞就執行擁塞避免或者擁塞檢測算法傳輸數據,直到網絡恢復正常。

慢開始算法
TCP從一個MSS(最大報文長度)報文開始,每次收到接收端的一個ACK後,就在原來MSS的基礎上增加一個MSS(擁塞窗口cwnd變為2),這樣當返回一個ACK的時候變為2個MSS長度的報文了,這兩個報文發送出去後如果再收到一個ACK,每個MSS報文又變為2個MSS的報文(擁塞窗口cwnd變為4)。所以經過兩次確認後,發送端可發送的報文為4個。以此類推,可以發現,可發送報文的長度是按照指數增長的。

wireshark tcp 擁塞控制_TCP

擁塞避免
擁塞避免是一種按照加法增大的算法,如果一直採用慢開始算法,那麼很快就會到達閾值,為了在網絡發生擁塞之前避免它,可以採用加法增大的算法,即每次cwnd只在原來的基礎增加1,直到網絡發生擁塞為止。

wireshark tcp 擁塞控制_窗口大小_02

擁塞檢測
既然叫檢測,那麼就是要讓發送方知道網絡發生了擁塞,那麼如何讓發送方知道網絡發生了擁塞呢?TCP中使用重傳機制讓發送方知道網絡發生了擁塞。而在TCP中發生重傳有兩種情況:RTO超時或者發送方連續收到三個重複的ACK確認。不管哪種情況,在擁塞檢測算法中,當傳輸速率到達ssthresh閾值的時候,都會把閾值較小為原來的一半,所以也叫乘法減小算法。
對於RTO超時,可以認為有比較大可能網絡發生了擁塞,所以早RTO超時的情況下,TCP採用的策略如下:

  1. ssthresh減小為原來的一半
  2. 把cwnd重新設為一個報文段大小
  3. 執行慢開始算法

對於收到三次重複的ACK確認,TCP認為發生擁塞的可能性不是特別大,於是採用如下策略:

  1. ssthresh減小為原來的一半
  2. 把cwnd的值設為ssthresh的值
  3. 執行擁塞避免算法

擁塞控制小結

由於剛開始不清楚網絡的擁塞情況,所以會首先採用慢開始算法,開始階段,窗口大小由1指數增大,直到窗口大小到達門限值。窗口大小到達門限值後,就開始執行擁塞避免算法,之後窗口值按照線性規律增大,直到出現超時或者到達最大的窗口大小值。這個時候,會開始執行擁塞擁塞算法,也就是把門限值變為窗口大小的一半,之後繼續執行擁塞避免算法,窗口大小按照線性規律增大。