1. 程式人生 > >趣談網路協議---TCP協議:因性惡而複雜,先惡後善反輕鬆

趣談網路協議---TCP協議:因性惡而複雜,先惡後善反輕鬆

TCP包頭格式 在這裡插入圖片描述

  • 序號解決包的亂序問題。
  • 確認序號確認對方收到,沒有收到則重新發送。
  • 狀態位維護連線的狀態。SYN發起連線,ACK回覆,RST重新連線,FIN結束連線。
  • 視窗大小用於流量控制。

TCP三次握手 在這裡插入圖片描述 為什麼是3次握手? 1、為了防止已失效的連線請求報文段突然又回到服務端。

兩次次握手:A的請求連線B的報文在網路中滯留,延誤到連線釋放後才到達B,B以為是A新發起的連線請求,同意建立連線,浪費了資源:埠、記憶體等。

而三次握手可防止上述情況發生,因為A不確認,B就不會建立連線。

大部分情況下,A和B建立連線後,A會馬上發資料。如果不發,B可以開啟keepalive,傳送探活包。B也可以對於長時間不發包的客戶端,主動關閉。

2、商量TCP包的序號。每個連線都要有不同的序號,起始序號隨時間變化。

TCP4次揮手 在這裡插入圖片描述 為什麼是4次揮手? 對於雙向連線,2次握手只是斷開單向連線,雙向斷開就需要4次揮手。第2、3次揮手不能合在一起,因為此時只能表明A不傳送資料了,B可能還有資料要傳送。

為什麼A第4次揮手確認了ACK後,再TIME-WATI狀態要等2MSL? 1、確認B收到最後的ACK。假如B沒有收到ACK,會超時重傳FIN,那麼A在2MSL內就能重新收到FIN,於是再發送ACK。

有一種異常情況,B超過2MSL仍然沒有收到ACK,即便重發FIN,A也不會再發送ACK了,而是傳送RST,這樣B就知道A已經離開。

2、防止已失效的報文段出現在下次連線中。A在傳送最後一個ACK之後,再經過經過2MSL,就可以使本連結持續時間內所產生的所有報文段都從網路中消失。從而保證在關閉連線後不會有還在網路中滯留的報文段去騷擾B。

TCP狀態機 在這裡插入圖片描述 如何實現一個靠譜的協議? 為保證順序性,每個包都有一個ID。

為保證不丟包,對於傳送的包都要進行應答,應答不是一個一個來,而是應答某個之前的ID,表示都收到了,稱累計確認或累計應答。

為記錄傳送包和接受包,在傳送端和接受端分別都有快取來儲存這些記錄。

流量控制 流量控制,通過滑動視窗控制傳送方的速度,防止將接收方塞滿。接收方在對包的確認中,會攜帶一個視窗大小,叫Advertised window。

傳送端: 在這裡插入圖片描述 接收端: 在這裡插入圖片描述 MaxRcvBuffer 為最大快取量。

NextByteExpected 和 LastByteRead 的差是還沒被應用層讀取的部分佔用掉 MaxRcvBuffer 的量,定義為 A。

AdvertisedWindow 其實是 MaxRcvBuffer 減去 A。

當接收方來不及處理,視窗中全是“接收已確認”,即視窗大小為0,傳送方會定時傳送視窗探測資料包。為防止低能視窗綜合徵,當視窗大小達到一定值,或為快取區一半時,才更新視窗。

順序問題和丟包問題 藉助滑動視窗解決。

假設4的確認到了,5的ACK丟了,6、7的資料包丟了。

1、一種方法是超時重傳。對每個傳送了但沒有收到ACK的包,設一個定時器,超時後重傳。時間應大於RTT,否則會引起不必要的重傳。

估計往返時間,需要TCP通過取樣RTT,然後加權平均。除了取樣RTT,還要取樣RTT的波動範圍,計算出一個估計的超時時間。稱自適應 重傳演算法(Adaptive Retransmission Algorithm)。

7再次超時,超時間隔加倍。兩次超時,不宜頻繁反覆傳送。

2、另一種是快速重傳。當接收方收到一個序號大於下一個所期望的報文段時,傳送3個冗餘的ACK,客戶端收到後,可在定時器過期前,重傳丟失的報文段。

3、還有一種方式時Selective Acknoledgment(SACK)。在TCP頭裡加SACK,可將快取地圖傳送給傳送方。例如可傳送ACK6、SASCK8、SACK9,傳送方 便可看出是7丟了。

擁塞控制問題 擁塞控制,通過擁塞視窗控制傳送方的速度,防止將網路塞滿。

LastByteSent - LastByteAcked <= min {cwnd, rwnd} ,擁塞視窗和滑動視窗共同控制傳送的速度。

如何判斷網路是否滿?丟包,超時重傳。

慢啟動階段:需要試探性的發包,一開始cwnd=1,收到一個確認加1,於是下次傳送2個包。視窗大小就會不斷翻倍,指數增長。

擁塞避免階段:視窗大小達到ssthresh後,開始線性增加。

直到出現丟包,ssthresh = cwnd / 2,cwnd = 1,重新開始慢啟動。

快速重傳:但將傳輸速度一下子降下來會導致網路卡頓,這時可以使用快速重傳。在超時前收到3個冗餘的ACK後,認為網路擁塞情況不是很嚴重,ssthresh = cwnd / 2,cwnd = cwnd / 2,當三個包返回時,cwnd = sshthresh + 3。

在這裡插入圖片描述 TCP的擁塞控制要避免的兩個現象是有問題的。

1、丟包不代表網路已滿。公網頻寬不滿也會丟包。

2、要等中間裝置的快取都填滿了,才發生丟包,降低速度為時已晚。

為優化這兩個問題,有了TCP BBR擁塞演算法。企圖找一個平衡點,通過不斷加快傳送速度,填滿網路,但不填滿中間裝置的快取,可達到高頻寬和低時延的平衡。