出現擁塞
擁塞控制是防止過多的數據注入到網絡中,使網絡中的路由器或鏈路不過載,這是一個全局性的。
流量控制是點對點的通信量的控制,是端到端問題。
擁塞控制方法
在最寬泛的級別上,我們可根據網絡層是否為運輸(傳輸)層擁塞控制提供顯示幫助,來區分擁塞控制方法。
端到端擁塞控制
在這種方式中,網絡層沒有為運輸層擁塞控制提供顯示支持。端系統必須通過對網絡行為的觀察(如分組丟失與時延)來推斷網絡是否出現擁塞。TCP必須通過端到端的方法來解決也擁塞控制,因為IP層不會向端系統提供有關網絡擁塞的反饋信息。TCP報文段的丟失(通過超時或3次冗余確認得知)被認為是網絡出現擁塞的一個跡象,TCP會相應地減小其窗口長度。
在TCP擁塞控制的一些最新建議也會使用往返時延RTT值的增加作為網絡擁塞程度增加的指示。
網絡輔助的擁塞控制
在網絡輔助的擁塞控制中,網絡層構件(即路由器)向發送方提供有關網絡中擁塞狀態的顯示反饋信息。
擁塞信息從網絡反饋到發送方通常有兩種方式:
- 直接反饋信息由網絡路由器發給發送方,這種通知方式常采用了一種阻塞分組(choke packet)的形式(含義為:“我阻塞了”)
- 顯示擁塞通知(Explicit Congestion Notification,ECN)。該方式由路由器標記或更新發送方流向接收方的分組中的某個字段(IP頭部的CE字段)來指示擁塞的產生。當接收方接收到這樣的分組后,就會向發送方發送網絡擁塞的通知(在回復的ACK的TCP字段置位ECN字段)。然而,這種方式需要至少需要一個完整的RTT。(使用網絡輔助的擁塞控制例子可參見ATM ABR擁塞控制)
關於TCP擁塞控制的三個問題
TCP使用的是端到端擁塞控制。TCP所采用的方法是讓每一個發送方根據感受到的網絡擁塞程度來限制其能向其連接發送流量的速率。由此可引出三個問題:①TCP發送方如何限制它向其連接發送流量的速率?②TCP發送方如何感知它到目的地之間的路徑上出現了擁塞?③當發送方感受到了端到端的時延,使用何種算法來改變其發送速率呢?下面我們一一分析。
TCP發送方如何限制它向其連接發送流量的速率?
一條TCP連接會建立一些狀態變量,比如LastByteRead、rwnd。運行在發送方的TCP擁塞控制即使會跟蹤一個變量,即擁塞窗口(congestion window)。擁塞窗口表示為cwnd,它對一個TCP發送方能向網絡中發送流量的速率進行了限制。需要注意在一個發送方中未被確認的數據量不會超過cwnd和rwnd中的最小值。即:
為了關注擁塞控制(與流量控制形成對比),我們后面假設TCP接收緩存足夠大,以至於忽略接受窗口rwnd的限制,發送方中未確認的數據量僅受限於cwnd。並且假設發送一直有數據要發送,即在擁塞窗口中的所有報文段都要被發送。
這些約束限制了發送方中未被確認的數據量,因此間接地限制了發送方的發送速率。
TCP發送方如何感知它到目的地之間的路徑上出現了擁塞?
當過度的擁塞出現時,在沿着這條路徑上的一台或者多台路由器的緩存會溢出,引起一個數據報(含TCP報文段)被丟棄。丟棄的數據報會引起發送方的丟包事件(超時或者受到三個冗余ACK),發送方就會認為到接收方的路徑上出現了擁塞指示。(收到3個冗余ACK時,會進行快重傳對丟失報文進行重傳而不必等到超時再重傳,因為超時重傳對發送速率影響很大,二者對擁塞控制的影響可見下文。前一篇文章簡要介紹了快速重傳,后面會補充快重傳為什么是要接收到3個冗余ACK)
TCP發送方如何確定它的發送速率?
發送方會接收到確認報文並且增加擁塞窗口長度,TCP可以被稱為是自計時(self-clocking)的。給定cwnd來控制發送速率可還是不知發送方如何確定它應當發送的速率。如果眾多發送方總體上發送地太快,它們會擁塞網絡,而發送地太慢又不可以充分利用網絡帶寬。
那TCP是如何確定它們的發送速率,既不會使網絡擁塞也不會浪費帶寬?TCP發送方式顯示地協作,或者存在一種分布式方法使得TCP發送方能夠基於本地信息設置它們的發送速率?
這里有一些指導性原則回答這些問題:
-
一個丟失的報文段意味着擁塞,因此當丟失報文段時應當降低TCP發送方的速率
-
對當前未確認的報文的確認到達時,能夠增加發送方的速率
確認報文的到達可以看做一些順利的指示,指示發送方報文段被順利地交付給接收方,網絡中沒有出現擁塞。因此,擁塞窗口長度可增加。
-
帶寬探測
ACK報文回復隱含地指示了從源到目的地的路徑上面沒有出現擁塞,丟包事件則指示出現了擁塞。由此,TCP便通過調節其傳輸速率增加影響ACK報文,如果出現丟包便減小傳輸速率,然后再進行增加速率,看擁塞狀況是否改變。
TCP擁塞控制算法
該算法主要包括3個主要部分:①慢啟動;②擁塞避免;③快速恢復。慢啟動和擁塞避免是TCP強制部分,兩者的差異在於對接收到的ACK做出反應時cwnd增加的長度。慢啟動比擁塞避免能更快的增加cwnd的長度。快速恢復是推薦部分,對TCP發送方並非是必需。
慢啟動
在慢啟動狀態,cwnd的值以一個MSS開始並當傳輸的報文首次被確認就增加一個MSS。如下圖所示,開始發送一個報文段,收到確認后擁塞窗口增加1。然后傳輸2個報文段,收到2個確認后增加擁塞窗口變成了4個MSS。這樣沒經過一個RTT,發送速率就會翻番。於是,TCP發送的起始速率慢,但是在慢啟動階段會以指數增長。
但是這樣會的增長何時終止呢?慢啟動對這個問題提供了幾種答案。
-
第一種: 如果出現一個有超時引起的丟包事件(即網絡中出現了擁塞),TCP發送方將cwnd設置為1並重新開始慢啟動過程。它還會將第二個狀態變量ssthresh(“慢啟動閾值”)設置為cwnd/2。
-
第二種: 與ssthresh相關。當增加到cwnd=ssthresh時,結束慢啟動並開始擁塞避免。
-
第三種: 如果檢測到3個冗余ACK,這時TCP執行快速重傳進入快速恢復狀態。
擁塞避免
進入擁塞狀態后,TCP的cwnd增加速率就比較緩慢,一個RTT將cwnd的值增加一個MSS,線性增長。例如,發送方在1個RTT時間內發送10個報文,那么收到所有10個確認報文后,擁塞窗口的值增加一個MSS。
在這個階段的cwnd增長停止時的情況:
-
超時
出現超時,\(ssthresh = 1/2 * cwnd\),cwnd被置為1個MSS,然后開始慢啟動
-
收到三個冗余ACK
TCP對於這種丟包事件,較與超時的做出的反應,比較溫和。TCP將cwnd減半(為使測量結果較好,計已收到的3個冗余ACK要加上3個MSS),並將ssthresh置為cwnd(未減半)的一半。然后進入快速恢復狀態。
快速恢復
在快速恢復中,對於引起TCP進入快速恢復狀態的缺失報文段,對收到的每個冗余的ACK,cwnd的值都增加一個MSS。最終,當對丟失報文段的一個ACK到達時,TCP在降低cwnd后進入擁塞避免狀態。如果出現超時事件:cwnd置為1個MSS,並且ssthresh置為cwnd的一半,遷移到慢啟動。
快速恢復是TCP推薦部件而不是必需。一種早期的TCP版本TCP Tahoe,不管是超時而引起的丟包還是3個冗余ACK引起的丟包事件,都會將cwnd置為1個MSS,並進入慢啟動階段。TCP較新的版本TCP Reno綜合了快速恢復算法。
附圖一張TCP擁塞控制流程圖

在每個RTT內cwnd線性增加1MSS,然后出現3個冗余ACK事件時cwnd減半(乘性減)。所以,TCP擁塞控制常被稱為加性增乘性減(Additive-Increase, Multiplicative-Decrease, AIMD)擁塞控制方式。
基於遲延的擁塞控制算法之TCP Vegas算法
TCP Vegas算法試圖在維持較好吞吐量的同是避免擁塞。基本思想是:①在分組丟失發生之前,在源與目的地之間檢測路由器中的擁塞;②當檢測出快發生分組丟失時,線性地降低發送速率。通過觀察RTT來預測分組是否要發生丟失。分組的RTT越長,路由器中的擁塞越嚴重。
快速重傳為什么是收到3次冗余ACK
對同一報文收到兩次ACK很有可能是報文段亂序造成的,收到3個及3個以上一定是丟包造成的!
依據經驗,收到3個duplicated ACK便可以啟動快重傳。
參考[知乎:TCP快速重傳為什么是三次冗余ack,這個三次是怎么定下來的?車小胖回答
](https://www.zhihu.com/question/21789252)后,作圖如下: