1. 程式人生 > >面試之路(29)-TCP流量控制和擁塞控制-滑動視窗協議詳解

面試之路(29)-TCP流量控制和擁塞控制-滑動視窗協議詳解

擁塞:

擁塞發生的主要原因在於網路能夠提供的資源不足以滿足使用者的需求,這些資源包括快取空間、鏈路頻寬容量和中間節點的處理能力。由於網際網路的設計機制導致其缺乏“接納控制”能力,因此在網路資源不足時不能限制使用者數量,而只能靠降低服務質量來繼續為使用者服務,也就是“盡力而為”的服務。
擁塞其實是一個動態問題,我們沒有辦法用一個靜態方案去解決,從這個意義上來說,擁塞是不可避免的。

重傳機制:

重發定時器
(1) 每一次一個包含資料的包被髮送(包括重發),如果該定時器沒有執行則啟動它,使得它在RTO秒之後超時(按照當前的RTO值)。
(2) 當所有的發出資料都被確認之後,關閉該重發定時器。
(3) 當接收到一個ACK確認一個新的資料,重新啟動該重發定時器,使得它在RTO秒之後超時(按照當前的RTO值)

流量控制(滑動視窗機制)

滑動視窗:

滑動視窗協議的基本原理就是在任意時刻,傳送方都維持了一個連續的允許傳送的幀的序號,稱為傳送視窗;同時,接收方也維持了一個連續的允許接收的幀的序號,稱為接收視窗。傳送視窗和接收視窗的序號的上下界不一定要一樣,甚至大小也可以不同。不同的滑動視窗協議視窗大小一般不同。傳送方視窗內的序列號代表了那些已經被髮送,但是還沒有被確認的幀,或者是那些可以被髮送的幀。

舉例解釋:

這裡寫圖片描述
傳送和接受方都會維護一個數據幀的序列,這個序列被稱作視窗。傳送方的視窗大小由接受方確定,目的在於控制傳送速度,以免接受方的快取不夠大,而導致溢位,同時控制流量也可以避免網路擁塞。下面圖中的4,5,6號資料幀已經被髮送出去,但是未收到關聯的ACK,7,8,9幀則是等待發送。可以看出傳送端的視窗大小為6,這是由接受端告知的(事實上必須考慮擁塞視窗cwnd,這裡暫且考慮cwnd>rwnd)。此時如果傳送端收到4號ACK,則視窗的左邊緣向右收縮,視窗的右邊緣則向右擴充套件,此時視窗就向前“滑動了”,即資料幀10也可以被髮送。

舉例2:

這裡寫圖片描述
一:初始態,傳送方沒有幀發出,傳送視窗前後沿相重合。接收方0號視窗開啟,等待接收0號幀;
二:傳送方開啟0號視窗,表示已發出0幀但尚確認返回資訊。 此時接收視窗狀態不變;
三:傳送方開啟0、1號視窗,表示0、1號幀均在等待確認之列。至此,傳送方開啟的視窗數已達規定限度,在未收到新的確認返回幀之 前,傳送方將暫停傳送新的資料幀。接收視窗此時狀態仍未變;
四:接收方已收到0號幀,0號視窗關閉,1號視窗開啟,表示準備接收1號幀。此時傳送視窗狀態不 變;
五:傳送方收到接收方發來的0號幀確認返回資訊,關閉0號視窗,表示從重發表中刪除0號幀。此時接收視窗狀態仍不變
六:傳送方繼續傳送2號幀,2號視窗 開啟,表示2號幀也納入待確認之列。至此,傳送方開啟的視窗又已達規定限度,在未收到新的確認返回幀之前,傳送方將暫停傳送新的資料幀,此時接收視窗狀態 仍不變;
七:接收方已收到1號幀,1號視窗關閉,2號視窗開啟,表示準備接收2號幀。此時傳送視窗狀態不變;
八:傳送方收到接收方發來的1號幀收畢的確認信 息,關閉1號視窗,表示從重發表中刪除1號幀。此時接收視窗狀態仍不變。

1位元滑動視窗協議

上面說的只是滑動視窗協議的理論,實際應用中又有不同。首先就是停等協議(stop-and-wait),這時接受方的視窗和傳送方的視窗大小都是1,1個位元就夠表示了,所以也叫1位元滑動視窗協議。傳送方這時自然傳送每次只能傳送一個,並且必須等待這個資料包的ACK,才能傳送下一個。雖然在效率上比較低,頻寬利用率明顯較低,不過在網路環境較差,或是頻寬本身很低的情況下,還是適用的。看下面的流程圖:
這裡寫圖片描述

後退n協議

停等協議雖然實現簡單,也能較好的適用惡劣的網路環境,但是顯然效率太低。所以有了後退n協議,這也是滑動視窗協議真正的用處,這裡傳送的視窗大小為n,接受方的視窗仍然為1。具體看下面的圖,這裡假設n=9:
首先發送方一口氣傳送10個數據幀,前面兩個幀正確返回了,資料幀2出現了錯誤,這時傳送方被迫重新發送2-8這7個幀,接受方也必須丟棄之前接受的3-8這幾個幀。
後退n協議的好處無疑是提高了效率,但是一旦網路情況糟糕,則會導致大量資料重發,反而不如上面的停等協議,實際上這是很常見的,具體可以參考TCP擁塞控制。
這裡寫圖片描述

選擇重傳協議

後退n協議的另外一個問題是,當有錯誤幀出現後,總是要重發該幀之後的所有幀,毫無疑問在網路不是很好的情況下會進一步惡化網路狀況,重傳協議便是用來解決這個問題。原理也很簡單,接收端總會快取所有收到的幀,當某個幀出現錯誤時,只會要求重傳這一個幀,只有當某個序號後的所有幀都正確收到後,才會一起提交給高層應用。重傳協議的缺點在於接受端需要更多的快取。

視窗的動作

稱視窗左邊沿向右邊沿靠近為視窗合攏。這種現象發生在資料被髮送和確認時。
當視窗右邊沿向右移動時將允許傳送更多的資料,我們稱之為視窗張開。這種現象發生在另一端的接收程序讀取已經確認的資料並釋放了T C P的接收快取時。
當右邊緣向左移動時,稱之為視窗收縮。

擁塞控制:

TCP的擁塞控制由4個核心演算法組成:“慢啟動”(Slow Start)、“擁塞避免”(Congestion voidance)、“快速重傳 ”(Fast Retransmit)、“快速恢復”(Fast Recovery)。

慢開始演算法

當主機開始傳送資料時,如果立即所大量資料位元組注入到網路,那麼就有可能引起網路擁塞,因為現在並不清楚網路的負荷情況。因此,較好的方法是先探測一下,即由小到大逐漸增大發送視窗,也就是說,由小到大逐漸增大擁塞視窗數值。通常在剛剛開始傳送報文段時,先把擁塞視窗 cwnd 設定為一個最大報文段MSS的數值。而在每收到一個對新的報文段的確認後,把擁塞視窗增加至多一個MSS的數值。用這樣的方法逐步增大發送方的擁塞視窗 cwnd ,可以使分組注入到網路的速率更加合理。
這裡寫圖片描述
慢開始的“慢”並不是指cwnd的增長速率慢,而是指在TCP開始傳送報文段時先設定cwnd=1,使得傳送方在開始時只發送一個報文段(目的是試探一下網路的擁塞情況),然後再指數增大cwnd。

為了防止擁塞視窗cwnd增長過大引起網路擁塞,還需要設定一個慢開始門限ssthresh狀態變數(如何設定ssthresh)。慢開始門限ssthresh的用法如下:

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

當 cwnd > ssthresh 時,停止使用慢開始演算法而改用擁塞避免演算法。

當 cwnd = ssthresh 時,既可使用慢開始演算法,也可使用擁塞控制避免演算法。

擁塞避免演算法

讓擁塞視窗cwnd緩慢地增大,即每經過一個往返時間RTT就把傳送方的擁塞視窗cwnd加1,而不是加倍。這樣擁塞視窗cwnd按線性規律緩慢增長,比慢開始演算法的擁塞視窗增長速率緩慢得多。

無論在慢開始階段還是在擁塞避免階段,只要傳送方判斷網路出現擁塞(其根據就是沒有收到確認),就要把慢開始門限ssthresh設定為出現擁塞時的傳送方視窗值的一半(但不能小於2)。然後把擁塞視窗cwnd重新設定為1,執行慢開始演算法。這樣做的目的就是要迅速減少主機發送到網路中的分組數,使得發生擁塞的路由器有足夠時間把佇列中積壓的分組處理完畢。
![這裡寫圖片描述](https://img-blog.csdn.net/20160510212745350)

<1>. 當TCP連線進行初始化時,把擁塞視窗cwnd置為1。前面已說過,為了便於理解,圖中的視窗單位不使用位元組而使用報文段的個數。慢開始門限的初始值設定為16個報文段,即 cwnd = 16 。

<2>. 在執行慢開始演算法時,擁塞視窗 cwnd 的初始值為1。以後傳送方每收到一個對新報文段的確認ACK,就把擁塞視窗值另1,然後開始下一輪的傳輸(圖中橫座標為傳輸輪次)。因此擁塞視窗cwnd隨著傳輸輪次按指數規律增長。當擁塞視窗cwnd增長到慢開始門限值ssthresh時(即當cwnd=16時),就改為執行擁塞控制演算法,擁塞視窗按線性規律增長。

<3>. 假定擁塞視窗的數值增長到24時,網路出現超時(這很可能就是網路發生擁塞了)。更新後的ssthresh值變為12(即變為出現超時時的擁塞視窗數值24的一半),擁塞視窗再重新設定為1,並執行慢開始演算法。當cwnd=ssthresh=12時改為執行擁塞避免演算法,擁塞視窗按線性規律增長,每經過一個往返時間增加一個MSS的大小。

強調:“擁塞避免”並非指完全能夠避免了擁塞。利用以上的措施要完全避免網路擁塞還是不可能的。“擁塞避免”是說在擁塞避免階段將擁塞視窗控制為按線性規律增長,使網路比較不容易出現擁塞。

快速重傳和快速恢復

重複確認:

傳送端有一個方法可以快速確認傳送端是不是出錯了,當丟失的資料包的後續資料包到達接收端時候,他們觸發給傳送端返回確認。這些確認號都是一樣的,叫做重複確認。

快速重傳

當發生三次重複確認,即使沒有超時,也會重傳,叫做快速重傳。重傳完畢,閥值減半,就像發生超時一樣,慢啟動開始,到了閥值,再線性增長。

快速恢復

安利一個面試題彙總的微信訂閱號。每天推送經典面試題和麵試心得技巧,都是乾貨!

微信訂閱號名稱:IT面試題彙總

微信訂閱號二維碼如下:

這裡寫圖片描述