TCP的擁塞控制
擁塞(congestion)
在某段時間,若對網絡中某一資源的需求超過了該資源所能提供的可用部分,網絡的性能就要變壞。
擁塞控制
擁塞控制就是防止過多的數據注入到網絡中,這樣可以使網絡中的路由器或鏈路不致過載。
如圖所示,橫坐標是提供的負載(offered load),代表單位時間內輸入給網絡的分組數目。縱坐標是吞吐量(throughput),代表單位時間內從網絡輸出的分組數目。
理想狀態:在吞吐量飽和之前,網絡吞吐量應等於提供的負載,故吞吐量曲線是45度的斜線。但當提供的負載超過某一限度時,由於網絡資源受限,吞吐量不再增長而保持為水平線,即吞吐量達到飽和。
實際狀態:隨着提供的負載的增大,網絡吞吐量的增大速率逐漸減小。也就是說,在網絡吞吐量還未達到飽和時,就已經有一部分的輸入分組被丟棄了。當網絡的吞吐量明顯的小於理想的吞吐量時,網絡就進入了輕度擁塞的狀態。當提供的負載達到某一數值時,網絡的吞吐量反而隨提供的負載的增大而下降,這時網絡就進入了擁塞狀態。當提供的負載繼續增大到某一數值時,網絡的吞吐量就下降到零,網絡無法工作,這就是所謂的死鎖(deadlock)。
幾種擁塞控制的方法
慢開始(slow-start)
發送方維持一個叫做擁塞窗口cwnd(congestion window)的狀態變量。擁塞窗口的大小取決於網絡的擁塞程度,並且動態的在變化。
慢開始的算法是這樣的:
如果立即把大量的數據字節注入到網絡,那么就有可能引起網絡阻塞,所以由小到大逐漸增大發送窗口數值,即由小到大逐漸增大擁塞窗口數值。
開始先設置cwnd = 1,發送第一個報文段M1,接收方收到后確認M1。發送方收到對M1的確認后,把cwnd從1增大到2,於是發送方接着發送M2和M3兩個報文段。接收方收到后發回對M2和M3的確認。發送方每收到一個對新報文段的確認,就使發送方的擁塞窗口加1,因此發送方收到兩個確認后,cwnd就從2增大到4,並可以發送M4-M7共4個報文段。因此使用慢開始算法后,每經過一個傳輸輪次,擁塞窗口cwnd就加倍。
為了防止擁塞窗口cwnd增長過大引起網絡擁塞,還需要設置一個慢開始門限ssthresh狀態變量。用法如下
當cwnd<ssthresh時,使用上述的慢開始算法。
當cwnd>ssthresh時,停止使用慢開始算法而改用擁塞避免算法。
當cwnd=ssthresh時,既可使用慢開始算法,也可使用擁塞避免算法。
擁塞避免算法(congestion avoidance)
算法思路:
讓擁塞窗口cwnd緩慢增大,即每經過一個往返時間RTT就把發送方的擁塞窗口cwnd加1,而不是加倍。這樣,擁塞窗口cwnd按線性規律緩慢增長,比慢開始短發的擁塞窗口增長速率緩慢很多。
實例:
(1)為了便於理解,途中的窗口單位不使用字節而使用報文段的個數。慢開始門限的初始值設置為16個報文段。即ssthresh=16。
(2)在執行慢開始算法時,擁塞窗口cwnd的初始值為1。擁塞窗口cwnd隨着傳輸輪次按指數規律增長。當擁塞窗口cwnd增長到慢開始門限ssthresh時,就改為執行擁塞避免算法,擁塞窗口按線性增長。
(3)假定擁塞窗口的數值增長到24時,網路出現超時。更新后的ssthresh值變為12(即為24的一半),擁塞窗口再設置為1,並開始慢開始算法。當cwnd=ssthresh=12時改為執行擁塞避免算法,擁塞窗口按線性規律增長。
快重傳(fast retransmit)
算法思路:
接收方每收到一個失序的報文段后就立即發出重復確認而不要等待自己發送數據時才捎帶確認。如圖所示,接收方收到了M1和M2后都分別發出了確認。現假定接收方沒有收到M3,但是收到了M4。顯然,接收方不能確認M4,因為M4是失序的報文段。根據可靠傳輸原理,接收方可以什么都不做,也可以在適當時機發送一次對M2的確認。但是在快重傳的規定里,接收方應及時發送對M2的重復確認,這樣做可以讓發送方及早知道報文段M3沒有達到接收方。發送方接着發送M5和M6。接受方收到后,也還要再次發出對M2的重復確認。這樣,發送方只要一連收到三個重復確認就應當立即重傳對方尚未收到的報文段M3,不必等到重傳計時器到期。
快恢復(fast recovery)
算法思想:
當發送方連續收到三個重復確認時,不執行慢開始算法,由於發送方現在認為網絡很有可能沒有發生擁塞,因此,與慢開始不同之處是現在不執行慢開始算法,而是把cwnd值設置為慢開始門限ssthresh減半后的數值,然后開始執行擁塞避免算法,使擁塞窗口緩慢地線性增大。如圖所示,TCP Reno版本就是在快重傳之后采用快恢復算法,而不是采用慢開始算法。