(二十七)運輸層--TCP的擁塞控制方法

TCP的擁塞控制方法

TCP進行擁塞控制的算法有四種,即慢開始、擁塞避免、快重傳、快恢復。爲了專注討論擁塞控制,假定:
(1)數據是單方向傳送的,對方只傳送確認報文
(2)接收方總是有足夠大的緩存空間,因而發送窗口的大小由網絡的擁塞程度來決定

下面討論的擁塞控制也叫做基於窗口的擁塞控制。爲此,發送方維持一個叫做擁塞窗口 cwnd 的狀態變量。擁塞窗口的大小取決於網絡的擁塞程度,並且動態變化。發送方讓自己的發送窗口等於擁塞窗口。

發送方控制擁塞窗口的原則是:只要網絡沒有出現擁塞。擁塞窗口就可以再增大一些,以便把更多的分組發送出去,這樣就可以提高網絡的利用率。但只要網絡出現擁塞或有可能出現擁塞,就必須把擁塞窗口減小一些,以減少注入到網絡中的分組數,以便緩解網絡出現的擁塞。

發送方如何知道網絡發生了擁塞呢?我們知道,當網絡發生擁塞時,路由器就要丟棄分組。因此只要發送方沒有按時收到應當到達的確認報文,就可以猜想網絡出現了擁塞。下面討論擁塞窗口的變化。

慢開始

當主機開始發送數據時,由於並不清楚網絡的負荷情況,所以如果立即把大量數據字節注入到網絡,就有可能引起網絡擁塞。經驗證明,較好的方法是先探測一下,即由小到大逐漸增大發送窗口(增大擁塞窗口數值)。

舊的規定是這樣的:在剛剛開始發送報文段時,先把初始擁塞窗口 cwnd 設置爲1至2個發送方的最大報文段(SMSS)數值,但新的 RFC 5681 把初始擁塞窗口 cwnd 設置爲不超過2至4個SMSS的數值,具體如下:

  • 若 SMSS > 2190字節,則設置初始擁塞窗口 cwnd = 2 x SMSS字節,且不得超過2個報文段

  • 若 1095字節 < SMSS ≤ 2190字節,則設置擁塞窗口 cwnd = 3 x SMSS字節,且不得超過3個報文段

  • 若 SMSS ≤ 1095字節,則設置初始擁塞窗口 cwnd = 4 x SMSS字節,且不得超過4個報文段

慢開始規定,在每收到一個對新的報文段的確認後,可以把擁塞窗口增加最多一個 SMSS 的數值。更具體些,就是:

擁塞窗口 cwnd 每次的增加量 = min(N, SMSS)

N是原先未被確認的,現在剛收到的確認報文段所確認的字節數。

下面舉個例子說明慢開始算法的原理。雖然TCP是用字節數作爲窗口大小的單位。但爲了敘述方便,以下是用報文段的個數作爲窗口大小的單位,這樣可以使用較小的數字來闡明擁塞控制的原理。

在一開始發送方先設置 cwnd = 1,發送第一個報文段M1,接收方收到後確認M1。發送方收到對M1的確認後,把 cwnd 從1增大到2,接着發送M2和M3兩個報文段。接收方收到後發回對M2和M3的確認。發送方每收到一個對新報文段的確認(重傳的不算在內),就使發送方的擁塞窗口加1。因此,發送方在收到兩個確認後,cwnd 就從2增大到4,並可發送M4~M7共4個報文段。可見使用慢開始算法後,每經過一個傳輸輪次,擁塞窗口就加倍。

上面使用了一個名詞——傳輸輪次。從上圖可以看出,一個傳輸輪次所經歷的時間就是往返時間RTT。使用傳輸輪次是更加強調:把擁塞窗口 cwnd 所允許發送的報文段都連續發送出去,並收到了對已發送的最後一個字節的確認。例如,擁塞窗口 cwnd 的大小是4個報文段,那麼這時的往返時間RTT就是發送方連續發送4個報文段,並收到這4個報文段的確認,總共經歷的時間。

慢開始的慢並不是指 cwnd 的增長速率慢,而是指TCP開始發送報文段時先設置 cwnd = 1,使得發送方在開始時只發送一個報文段,然後再逐漸增大 cwnd,這當然比設置大的 cwnd 值一下子把許多報文段注入到網絡中要“慢得多”。這對防止網絡出現擁塞是一個非常好的方法。

在TCP的實際運行中,發送方只要收到一個對新報文段的確認,其擁塞窗口 cwnd 就立即加1,並可以立即發送新的報文段,而不需要等這個輪次中所有的確認都收到後,再發送新的報文段。

爲了防止擁塞窗口 cwnd 增長過大引起網絡擁塞,還需要設置一個 慢開始門限 狀態變量。慢開始門限 ssthresh 的用法如下:

  • 當 cwnd < ssthresh 時,使用上述的慢開始算法

  • 當 cwnd > ssthresh 時,使用下述的擁塞避免算法

  • 當 cwnd = ssthresh 時,即可使用慢開始算法,也可使用擁塞避免算法

擁塞避免

擁塞避免的思路是讓擁塞窗口 cwnd 緩慢的增大,即每經過一個往返時間 RTT 就把發送方的擁塞窗口 cwnd 加1,而不是像慢開始階段那樣加倍增長。即在擁塞避免階段,擁塞窗口 cwnd 按線性規律緩慢增長,比慢開始算法的擁塞窗口增長速率緩慢很多。

下圖用具體例子說明了在擁塞控制的過程中,TCP的擁塞窗口 cwnd 是怎樣變化的。現假定TCP的發送窗口等於擁塞窗口。

當TCP連接進行初始化時,把擁塞窗口 cwnd 置爲1。在本例中,慢開始門限的初始值設置爲16個報文段,即 ssthresh = 16。在執行慢開始算法時,發送方每收到一個對新報文段的確認ACK,就把擁塞窗口值加1,然後開始下一輪的傳輸,擁塞窗口 cwnd 隨着傳輸輪次按指數規律增長。當擁塞窗口 cwnd 增長到慢開始門限值 ssthresh時,按線性規律增長。但擁塞避免並非完全能夠避免擁塞,只是說控制爲按線性規律增長,使網絡比較不容易出現擁塞。

當擁塞窗口 cwnd = 24 時,網絡出現了超時,發送方判斷爲網絡擁塞。於是調整門限值 ssthresh = cwnd / 2 = 12,同時設置擁塞窗口 cwnd = 1,重新進入慢開始階段。按照慢開始算法,發送方每收到一個對新報文段的確認ACK,就把擁塞窗口值加1。當擁塞窗口 cwnd = ssthresh = 12時,改爲執行擁塞避免算法,擁塞窗口按線性規律增大。

快重傳

如上圖,當擁塞窗口 cwnd = 16時,出現了一個新的情況,就是發送方一連收到3個對同一個報文段的重複確認。有時個別報文段會在網絡中丟失,但實際上網絡並未發生擁塞。如果發送方遲遲收不到確認,就會產生超時,就會誤認爲網絡發生了擁塞。這就導致發送方錯誤的啓動慢開始,把擁塞窗口 cwnd 又設置爲1,因而降低了傳輸效率。

採用快重傳算法可以讓發送方儘早知道發生了個別報文段的丟失。快重傳算法首先要求接收方不要等待自己發送數據時才進行稍待確認,而是要立即發送確認,即使收到了失序的報文段,也要立即發出對已收到的報文段的重複確認。如下圖所示,接收方收到了M1和M2後都分別及時發出了確認。現假定接收方沒有收到M3,但卻收到了M4。本來接收方可以什麼也不做,但按照快重傳算法,接收方必須立即發送對M2的重複確認,以便讓發送方及早知道接收方沒有收到報文段M3。發送方共收到了接收方的4個對M2的確認,其中後3個都是重複確認。快重傳算法規定,發送方只要一連收到3個重複確認,就知道接收方確實沒有收到報文段M3,應當立即進行重傳。使用快重傳可以使整個網絡的吞吐量提高約20%。

快恢復

因此,上上圖中的點4,發送方知道現在只是丟失了個別的報文段。於是不啓動慢開始,而是執行快恢復算法。這時,發送方調整門限值 ssthresh = cwnd / 2 = 8,同時設置擁塞窗口 cwnd = ssthresh = 8(節點5),並開始執行擁塞避免算法。

有的快恢復實現是把快恢復開始時的擁塞窗口 cwnd 值在增大一些(增大3個報文段的長度),即等於新的 ssthresh + 3 x MSS。這樣做的理由是:既然發送方收到3個重複的確認,就表明有3個分組已經離開了網絡。這3個分組不再消耗網絡的資源而是停留在接收方的緩存中(因爲發出了3個重複的確認)。可見現在網絡中並不是堆積了分組而是減少了3個分組,因此可以適當把擁塞窗口擴大一些。

根據以上所述,TCP的擁塞控制可以歸納爲下面這個流程圖:

本文的討論假定了接收方總是有足夠大的緩存空間,因而發送窗口的大小由網絡的擁塞程度來決定。但實際上接收方的緩存空間總是有限的。接收方根據自己的接收能力設定了接收方窗口 rwnd,並把這個窗口值寫入TCP首部中的窗口字段,傳送給發送方。因此,接收方窗口又稱爲通知窗口。從接收方對發送方的流量控制的角度考慮,發送方的發送窗口一定不能超過對方給出的接收方窗口值。

如果把擁塞控制和接收方對發送方的流量控制一起考慮,那麼很顯然,發送方的窗口的上限值應當取爲接收方窗口 rwnd 和擁塞窗口 cwnd 這兩個變量中較小的一個。(較小的那個值控制了發送方發送數據的速率)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章