TCP 協議中的 Window Size與吞吐量


 

為了獲得最優的連接速率,使用TCP窗口來控制流速率(flow control),滑動窗口就是一種主要的機制。這個窗口允許源端在給定連接傳送數據分段而不用等待目標端返回ACK,一句話描述:窗口的大小決定在不需要對端響應(acknowledgement)情況下傳送數據的數量。​官方定義:“The amount of octets that can be transmitted without receiving an acknowledgement from the other side”。

 

 

 

TCP窗口機制

​​TCP header中有一個Window Size字段,它其實是指接收端的窗口,即接收窗口,用來告知發送端自己所能接收的數據量,從而達到一部分流控的目的。其實TCP在整個發送過程中,也在度量當前的網絡狀態,目的是為了維持一個健康穩定的發送過程,比如擁塞控制。因此,數據是在某些機制的控制下進行傳輸的,就是窗口機制。發送端的發送窗口是基於接收端的接收窗口來計算的,也就是我們常說的TCP是有連接的發送,數據傳輸需要對端確認,發送的數據分為如下四類來看

窗口滑動發送數據

(1)已經發送並且對端確認(Sent/ACKed)---------------發送窗外 緩沖區外

(2)已經發送但未收到確認數據(Sent/UnACKed)----- --發送窗內 緩沖區內​

(3)允許發送但尚未防的數據​(Unsent/Inside)-----------發送窗內 緩沖區內​

(4)未發送暫不允許(Unsent/Outside)-------------------發送窗外 緩沖區內​

TCP窗口就是這樣逐漸滑動,發送新的數據,滑動的依據就是發送數據已經收到ACK,確認對端收到,才能繼續窗口滑動發送新的數據。可以看到窗口大小對於吞吐量有着重要影響,同時ACK響應與系統延時又密切相關。需要說明的是:如果發送端的窗口過大會引起接收端關閉窗口,處理不過來反之,如果窗口設置較小,結果就是不能充分利用帶寬,所以仔細調節窗口對於適應不同延遲和帶寬要求的系統很重要

TCP窗口大小

最早TCP協議涉及用來大范圍網絡傳輸時候,其實是沒有超過56Kb/s的​連接速度的。因此,TCP包頭中只保留了16bit用來標識窗口大小,允許的最大緩存大小不超過64KB。為了打破這一限制,RFC1323規定了TCP窗口尺寸選擇,是在TCP連接開始的時候三步握手的時候協商的(SYN, SYN-ACK,ACK),會協商一個  Window size scaling factor,之后交互數據中的是Window size value,所以最終的窗口大小是二者的乘積.

Window size value: 64 or 0000 0000 0100 0000 (16 bits) 

​Window size scaling factor: 256 or 2 ^ 8 (as advertised by the 1st packet) 

The actual window size is 16,384 (64 * 256)

這里的窗口大小就意味着,直到發送16384個字節,才會停止等待對方的ACK.隨着雙方回話繼續,窗口的大小可以修改window size value 參數完成變窄或變寬,但是注意:Window size scaling factor乘積因子​必須保持不變。在RFC1323中規定的偏移(shift count)是14,也就是說最大的窗口可以達到Gbit,很大。

 Wireshark抓包實例

這一機制並不總是默認開啟的和系統有關,貌似Linux默認開啟,Windows默認關閉。

​TCP窗口的參數設置

TCP窗口起着控制流量的作用,實際使用時這是一個雙端協調的過程,還涉及到TCP的慢啟動​(Rapid Increase/Multiplicative Decrease),擁塞避免,擁塞窗口和擁塞控制。可以記住,發送速率是由min(擁塞窗口,接收窗口),接收窗口在下文有講。

TCP窗口優化設置​

TCP​窗口既然那么重要,那要怎么設置,一個簡單的原則是2倍的BDP.這里的BDP的意思是bandwidth-delay product,也就是帶寬和時延的乘積,帶寬對於網絡取最差連接的帶寬。

buffer size = 2 * bandwidth * delay​

還有一種簡單的方式,使用ping來計算網絡的環回時延(RTT),然后表達為:

buffer size = bandwidth * RTT​

​為什么是2倍?因為可以這么想,如果滑動窗口是bandwidth*delay,當發送一次數據最后一個字節剛到時,對端要回ACK才能繼續發送,就需要等待一次單向時延的時間,所以當是2倍時,剛好就能在等ACK的時間繼續發送數據,等收到ACK時數據剛好發送完成,這樣就提高了效率。

舉個例子:帶寬是20Mbps,通過ping我們計算單向時延是20ms,那么可以計算:20000000bps*8*0.02 = 52,428bytes​,因此我們最優窗口用 104,856 bytes = 2 x 52,428,所以說當發送者發送104,856 bytes數據后才需要等待一個ACK響應,當發送了一半的時候,對端已經收到並且返回ACK(理想情況),等到ACK回來,又把剩下的一半發送出去了,所以發送端就無需等待ACK返回。

發現了么?這里的窗口已經明顯大於64KB了,所以機制改善了,上一級。

TCP窗口流量控制​

​現在我們看看到底如何控制流量。TCP在傳輸數據時和windows size 關系密切,本身窗口用來控制流量,在傳輸數據時,發送方數據超過接收方就會丟包,流量控制,流量控制要求數據傳輸雙方在每次交互時聲明各自的接收窗口「rwnd」大小,用來表示自己最大能保存多少數據,這主要是針對接收方而言的,通俗點兒說就是讓發送方知道接收方能吃幾碗飯,如果窗口衰減到零,也就是發送方不能再發了,那么就說明吃飽了,必須消化消化,如果硬撐脹漏了,那就是丟包了。

流量控制

慢啟動     雖然流量控制可以避免發送方過載接收方,但是卻無法避免過載網絡,這是因為接收窗口「rwnd」只反映了服務器個體的情況,卻無法反映網絡整體的情況。

為了避免網絡過載,慢啟動引入了擁塞窗口「cwnd」的概念,用來表示發送方在得到接收方確認前,最大允許傳輸的未經確認的數據。「cwnd」同「rwnd」相比不同的是:它只是發送方的一個內部參數,無需通知給接收方,其初始值往往比較小,然后隨着數據包被接收方確認,窗口成倍擴大,有點類似於拳擊比賽,開始時不了解敵情,往往是次拳試探,慢慢心里有底了,開始逐漸加大重拳進攻的力度。

擁塞窗口擴大

在慢啟動的過程中,隨着「cwnd」的增加,可能會出現網絡過載,其外在表現就是丟包,一旦出現此類問題,「cwnd」的大小會迅速衰減,以便網絡能夠緩過來。

擁塞窗口與丟包

說明:網絡中實際傳輸的未經確認的數據大小取決於「rwnd」和「cwnd」中的小值。

擁塞避免​  從慢啟動的介紹中,我們能看到,發送方通過對「cwnd」大小的控制,能夠避免網絡過載,在此過程中,丟包與其說是一個網絡問題,倒不如說是一種反饋機制,通過它我們可以感知到發生了網絡擁塞,進而調整數據傳輸策略,實際上,這里還有一個慢啟動閾值「ssthresh」的概念,如果「cwnd」小於「ssthresh」,那么表示在慢啟動階段;如果「cwnd」大於「ssthresh」,那么表示在擁塞避免階段,此時「cwnd」不再像慢啟動階段那樣呈指數級整整,而是趨向於線性增長,以期避免網絡擁塞,此階段有多種算法實現,通常保持缺省即可,這里就不一一說明了。

如何調整「rwnd」到一個合理值  很多時候TCP的傳輸速率異常偏低,很有可能是接收窗口「rwnd」過小導致,尤其對於時延較大的網絡,實際上接收窗口「rwnd」的合理值取決於BDP的大小,也就是帶寬和延遲的乘積。假設帶寬是 100Mbps,延遲是 100ms,那么計算過程如下:

BDP = 100Mbps * 100ms = (100 / 8) * (100 / 1000) = 1.25MB​

 

​此問題下如果想最大限度提升吞度量,接收窗口「rwnd」的大小不應小於 1.25MB。

如何調整「cwnd」到一個合理值 一般來說「cwnd」的初始值取決於MSS的大小,計算方法如下:

min(4 * MSS, max(2 * MSS, 4380))

以太網標准的MSS大小通常是1460,所以「cwnd」的初始值是3MSS。當我們瀏覽視頻或者下載軟件的時候,「cwnd」初始值的影響並不明顯,這是因為傳輸的數據量比較大,時間比較長,相比之下,即便慢啟動階段「cwnd」初始值比較小,也會在相對很短的時間內加速到滿窗口,基本上可以忽略不計。下圖使用IxChariot完成一次設置​

設置cwnd

   不過當我們瀏覽網頁的時候,情況就不一樣了,這是因為傳輸的數據量比較小,時間比較短,相比之下,如果慢啟動階段「cwnd」初始值比較小,那么很可能還沒來得及加速到滿窗口,通訊就結束了。這就好比博爾特參加百米比賽,如果起跑慢的話,即便他的加速很快,也可能拿不到好成績,因為還沒等他完全跑起來,終點線已經到了

結語​

文中大量參考下面博客內容,比如最后一節幾乎完全來自於第一個博客,詳細內容跳轉鏈接,學習總結,記錄一下。​

https://huoding.com/2013/11/21/299

https://my.oschina.net/greki/blog/264061​

​http://www.cnblogs.com/woaiyy/p/3554182.html

人生有些關口非狠狠的斗一下不可,不能為了混口飯吃而自甘蹉跎。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM