1. 程式人生 > >TCP協議的滑動視窗具體是怎樣控制流量的?

TCP協議的滑動視窗具體是怎樣控制流量的?

1)TCP滑動視窗分為接受視窗,傳送視窗
滑動視窗協議是傳輸層進行流控的一種措施,接收方通過通告發送方自己的視窗大小,從而控制傳送方的傳送速度,從而達到防止傳送方傳送速度過快而導致自己被淹沒的目的。

對ACK的再認識,ack通常被理解為收到資料後給出的一個確認ACK,ACK包含兩個非常重要的資訊:
一是期望接收到的下一位元組的序號n,該n代表接收方已經接收到了前n-1位元組資料,此時如果接收方收到第n+1位元組資料而不是第n位元組資料,接收方是不會發送序號為n+2的ACK的。舉個例子,假如接收端收到1-1024位元組,它會發送一個確認號為1025的ACK,但是接下來收到的是2049-3072,它是不會發送確認號為3072的ACK,而依舊傳送1025的ACK。

二是當前的視窗大小m,如此傳送方在接收到ACK包含的這兩個資料後就可以計算出還可以傳送多少位元組的資料給對方,假定當前傳送方已傳送到第x位元組,則可以傳送的位元組數就是y=m-(x-n).這就是滑動視窗控制流量的基本原理




重點:傳送方根據收到ACK當中的期望收到的下一個位元組的序號n以及視窗m,還有當前已經發送的位元組序號x,算出還可以傳送的位元組數。


傳送端視窗的第一個位元組序號一定是ACK中期望收到的下一個位元組序號,比如下圖:
<img src="https://pic1.zhimg.com/9c21786770459afa47bfa2e4606cc454_b.png" data-rawwidth="667" data-rawheight="216" class="origin_image zh-lightbox-thumb" width="667" data-original="https://pic1.zhimg.com/9c21786770459afa47bfa2e4606cc454_r.png">上圖52 53 54 55 位元組都是可以新發送的位元組序
上圖52 53 54 55 位元組都是可以新發送的位元組序


接受端視窗的第一個位元組序之前一定是已經完全接收的,後面窗口裡面的資料都是希望接受的,視窗後面的資料都是不希望接受的。



http://blog.chinaunix.net/uid-20778955-id-539945.html

http://www.netis.com.cn/flows/2012/08/tcp-%E6%BB%91%E
5%8A%A8%E7%AA%97%E5%8F%A3%E7%9A%84%E7%AE%80%E4%BB%8B/


TCP的滑動視窗分為接收視窗和傳送視窗
不分析這兩種視窗就討論是不妥當的。

TCP的滑動視窗主要有兩個作用,一是提供TCP的可靠性,二是提供TCP的流控特性。同時滑動視窗機制還體現了TCP面向位元組流的設計思路。TCP 段中視窗的相關欄位。
<img src="https://pic2.zhimg.com/d6b970fb6d44aafeeec4a4c9d61a9225_b.png" data-rawwidth="620" data-rawheight="197" class="origin_image zh-lightbox-thumb" width="620" data-original="https://pic2.zhimg.com/d6b970fb6d44aafeeec4a4c9d61a9225_r.png">

TCP的Window是一個16bit位欄位,它代表的是視窗的位元組容量,也就是TCP的標準視窗最大為2^16-1=65535個位元組。

另外在TCP的選項欄位中還包含了一個TCP視窗擴大因子,option-kind為3,option-length為3個位元組,option-data取值範圍0-14。視窗擴大因子用來擴大TCP視窗,可把原來16bit的視窗,擴大為31bit。

滑動視窗基本原理

1)對於TCP會話的傳送方,任何時候在其傳送快取內的資料都可以分為4類,“已經發送並得到對端ACK的”,“已經發送但還未收到對端ACK的”,“未傳送但對端允許傳送的”,“未傳送且對端不允許傳送”。“已經發送但還未收到對端ACK的”和“未傳送但對端允許傳送的”這兩部分資料稱之為傳送視窗。

<img src="https://pic1.zhimg.com/a1d5c050ad957880094a5f003b1ccd24_b.png" data-rawwidth="664" data-rawheight="177" class="origin_image zh-lightbox-thumb" width="664" data-original="https://pic1.zhimg.com/a1d5c050ad957880094a5f003b1ccd24_r.png">當收到接收方新的ACK對於傳送視窗中後續位元組的確認是,視窗滑動,滑動原理如下圖。當收到接收方新的ACK對於傳送視窗中後續位元組的確認是,視窗滑動,滑動原理如下圖。


<img src="https://pic1.zhimg.com/9c21786770459afa47bfa2e4606cc454_b.png" data-rawwidth="667" data-rawheight="216" class="origin_image zh-lightbox-thumb" width="667" data-original="https://pic1.zhimg.com/9c21786770459afa47bfa2e4606cc454_r.png">

當收到ACK=36時視窗滑動。

2)對於TCP的接收方,在某一時刻在它的接收快取記憶體在3種。“已接收”,“未接收準備接收”,“未接收並未準備接收”(由於ACK直接由TCP協議棧回覆,預設無應用延遲,不存在“已接收未回覆ACK”)。其中“未接收準備接收”稱之為接收視窗。

傳送視窗與接收視窗關係

TCP是雙工的協議,會話的雙方都可以同時接收、傳送資料。TCP會話的雙方都各自維護一個“傳送視窗”和一個“接收視窗”。其中各自的“接收視窗”大小取決於應用、系統、硬體的限制(TCP傳輸速率不能大於應用的資料處理速率)。各自的“傳送視窗”則要求取決於對端通告的“接收視窗”,要求相同。

<img src="https://pic4.zhimg.com/c798dd393fcf7c03b1db78f5bcf0304b_b.png" data-rawwidth="675" data-rawheight="527" class="origin_image zh-lightbox-thumb" width="675" data-original="https://pic4.zhimg.com/c798dd393fcf7c03b1db78f5bcf0304b_r.png">

滑動視窗實現面向流的可靠性

1)最基本的傳輸可靠性來源於“確認重傳”機制。

2)TCP的滑動視窗的可靠性也是建立在“確認重傳”基礎上的。

3)傳送視窗只有收到對端對於本段傳送視窗內位元組的ACK確認,才會移動傳送視窗的左邊界。

4)接收視窗只有在前面所有的段都確認的情況下才會移動左邊界。當在前面還有位元組未接收但收到後面位元組的情況下,視窗不會移動,並不對後續位元組確認。以此確保對端會對這些資料重傳。


滑動視窗的流控特性

TCP的滑動視窗是動態的,我們可以想象成小學常見的一個數學題,一個水池,體積V,每小時進水量V1,出水量V2。當水池滿了就不允許再注入了,如果有個液壓系統控制水池大小,那麼就可以控制水的注入速率和量。這樣的水池就類似TCP的視窗。應用根據自身的處理能力變化,通過本端TCP接收視窗大小控制來對對對端的傳送視窗流量限制。

應用程式在需要(如記憶體不足)時,通過API通知TCP協議棧縮小TCP的接收視窗。然後TCP協議棧在下個段傳送時包含新的視窗大小通知給對端,對端按通知的視窗來改變傳送視窗,以此達到減緩傳送速率的目的。