TCP采用個各種辦法來減少流量的傳輸量以及信道的利用率,
延時確認-減少傳輸數量
TCP允許延遲一會再發送ACK,這樣可以將ACK和相同方向的資料結合起來進行發送,從而降低ACK的數量,在一定程度上減輕網路負載,

圖中通過延遲ACK減少了一個ACK的傳輸數量
滑動視窗
滑動視窗的作業原理在之前已經做了詳細的介紹,在滑動視窗中有一個很重要的概念:視窗大小,問題來了,TCP是如何設定視窗大小的呢?在介紹之前先看一下TCP的快取結構,

對于TCP來說接收和發送方都維護著一個快取,看上圖會發現個問題:如果寫行程寫的速度大于讀行程的讀取速度,這樣會導致接收快取溢位,最終導致發送失敗,所以引入了視窗大小的概念,接收方通過ACK來實時告知發送方自己剩余快取的大小(即自己還能接收多少資料),這個大小就是滑動視窗的大小,在傳輸的程序中,每一次ack接收方會根據自己的快取大小動態的調整視窗的大小,下圖詳細展示了這一程序,

0視窗(Zero Window)
上面滑動視窗的展示中最終發送視窗變成了0.
當發送方收到視窗為0的引數后,便不再發送資料給接收方,這個時候接收方行程一直在讀取資料,最終接收方的TCP快取會清空,有空間接收資料,這個時候接收方會通過一個ack通知發送方視窗的大小,但是這個ack有可能會丟失(ack沒有重傳功能),發送方因為視窗時0,一直沒有發送資料,所以無法得知最新的視窗大小,通信雙方都進入了一直等待狀態,
為了解決這個問題,TCP為每一個鏈接設計了一個持續計數器(persistence timer),當視窗大小為0時,就會啟動這個計數器,當計數器到期后會發送一個零視窗(zero window)探測報文段(一個位元組),接收方通過確認這個探測報文時可以告知發送方最新的視窗大小,(TCP規定,就算視窗為0,也要接收零視窗探測報文),下圖展示了這種case,

糊涂視窗綜合征(Silly Window Syndrome-SWS)
通俗來解釋這個場景就是一架可以坐500人的飛機只拉1個乘客和5個機組人員,資源極大的浪費,
以太網最大傳輸單元(MTU:max transmission unit)為1500位元組,TCP+IP的頭部欄位為40位元組,所以TCP的最大報文(MSS:Max segment size)長度為1460位元組,當傳遞的報文的大小遠遠小于1460,尤其小于頭部40的時候,就出現了上面說的一個大飛機拉一個人的情況,其中MTU為飛機的容量(500),機組乘員為TCP/IP頭部(5),傳輸報文為乘客(1),
發送端引起的SWS
發送視窗的size大于MSS,但是需要發送的資料遠遠小于MSS,這種情況的解決采用nagle演算法:
if there is new data to send #有資料要發送
# 發送視窗緩沖區和佇列資料 >=mss,佇列資料(available data)為原有的佇列資料加上新到來的資料
# 也就是說緩沖區資料超過mss大小,nagle演算法盡可能發送足夠大的資料包
if the window size >= MSS and available data is >= MSS
send complete MSS segment now # 立即發送
else
if there is unconfirmed data still in the pipe # 前一次發送的包沒有收到ack
# 將該包資料放入佇列中,直到收到一個ack再發送緩沖區資料
enqueue data in the buffer until an acknowledge is received
else
send data immediately # 立即發送
end if
end if
end if
else里面有小塊資料(小于MSS)時候,解釋下:這個時候需要看是否還有已經發送待確認的資料,如果有則等著先不發,等于先在發送端攢資料,某種程度上又變成了停等協議,如果ACK回傳的比較慢,小資料等待的時間就會比較長,最侄訓影響性能,有些情況并不適用nagle演算法,比如人機互動的游戲等,可以禁用nagle演算法,
接收端引起的SWS
對于接收端來說,如果接收快取的視窗大小小于MSS或者某個給定的值后,直接ack 接收視窗的size為0,這樣當發送方收到接收視窗為0時,則停止發送資料進行等待,在此期間,接收端的應用一直在讀取資料,這樣接收視窗會慢慢變大,最終通過發送方的0視窗探測請求告知發送方最新的視窗大小,從而再次開始資料傳輸,
以上介紹了TCP流量控制的一個整體程序,全文完,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/209911.html
標籤:其他
