1. 程式人生 > >深入淺出圖解【計算機網路】 之 【TCP可靠傳輸的實現: 三次握手+滑動視窗】

深入淺出圖解【計算機網路】 之 【TCP可靠傳輸的實現: 三次握手+滑動視窗】

【前言】這個系列主要會介紹一些計算機網路體系中“看上去稍有些複雜”但“一旦理解了又會很容易”的內容,我會嘗試通過示意圖/動圖的方式對概念進行儘量直觀的詮釋,如果能夠對大家學習計算機網路有所啟發的話就最好了。

TCP(Transmission Control Protocol)是整個TCP/IP協議族中為數不多的能扛起“可靠傳輸”大旗的“扛把子”了(上有應用層協議嗷嗷待哺,下有IP協議寄予厚望(注:IP協議是不提供可靠傳輸服務的))能夠肩負如此重任說明它的協議組成一定不簡單,不過,作為一個“協議”,它一定也不會很難理解的。

這部分的內容我打算分為兩個部分講解,本篇文章主要會講解TCP連線的建立和釋放(三次握手+四次握手),以及傳送端的滑動視窗一般原理;至於同樣很重要的“擁塞控制”等內容,我會放到下一篇文章中。

說起TCP,我們應該瞭解它最突出的特點是“基於連線的傳輸”和“以位元組為單位(面向位元組流)”,這兩點特點與同是運輸層的UDP協議形成了鮮明對比。(UDP不建立連線,以報文為單位,兩者的區別有機會會仔細說說)而實現這兩點也是TCP能夠提供可靠傳輸的關鍵。

預備知識

TCP報文結構

TCP_packet

下面簡單解釋一下報文中一些重要的部分:

  • 源埠和目的埠:各佔兩個位元組(16位),埠(Port)是運輸層與應用層的服務介面,以實現複用和分用。
  • 序號(sequence number):佔4個位元組,指本報文段所傳送的資料的第一個位元組的序號。
  • 確認號(acknowledgement number)
    :同樣佔4個位元組,是期望收到對方下一個報文段的第一個位元組的序號。(即收到對方的報文段最後一個位元組的序號加一)
  • (部分)標誌位(Flags)
    • 確認(ACK):ACK=1時確認號欄位(acknowledgement number)才有效;
    • 同步(SYN):SYN=1表示這是一個“連線請求(SYN)”或“連線接受(SYN-ACK)”報文;
    • 終止(FIN):用於釋放連線,FIN=1表明報文段傳送完畢,要求釋放連線。
  • 視窗:佔2位元組,是用來讓對方設定傳送視窗的依據。

面向流的TCP協議

再瞭解了TCP報文結構之後,我們需要知道,這裡的“報文”與我們常見的“報文”有些不同。

TCP 不關心應用程序一次把多長的報文傳送到 TCP 快取。這和UDP的“給多少裝多少”正相反。
TCP 對連續的位元組流進行分段,形成 TCP 報文段。
面向位元組流

那麼分段的依據是什麼呢?
TCP在建立連線的基礎上,傳送方可以根據對方給出的視窗值(接下來要提到的:使用滑動視窗實現流量控制)和當前網路擁塞(下一篇文章將要提到的:擁塞控制機制)的程度來決定一個報文段應包含多少個位元組(UDP 傳送的報文長度是應用程序給出的)。

TCP連線的建立(“三次握手”)與釋放(“四次握手”)

TCP 建立連線的過程叫做“握手”(handshake),可以說是一個頗經典的不那麼貼切但為大家所普遍接受的擬人化稱呼。

在連線的建立階段,需要在客戶和伺服器之間交換三個 TCP 報文段。稱之為三報文握手(there-way handshake)
3_way_handshake

三報文握手的過程就如上動圖所示,是不是其實很簡單。
就像是兩個隔著很遠的人在測試一個電話線路:
“能聽見我說話嗎?”
“聽見了!能聽見我說話嗎?”
“聽見了!”

與建立連線思路相似的,還有“四報文握手”(four-way handshake)的連線釋放
4_way_handshake

與建立連線不同的是,如果某一方想要釋放連線,另一方“不一定”就想跟著釋放連線,因為它可能還有東西沒傳完呢。
就像是倆人打電話嘮了很久,其中有個人想要睡了:
“喂,我困了,咱明天再聊吧”
“哦哦,那我最後說幾句”
... ...
“好,我說完了,晚安咯”
“晚安”

使用滑動視窗實現可靠傳輸+流量控制

滑動視窗,實際上就是傳送方能連續發出的資料(位元組流)的閾值。

現在假設,A收到了B發來的確認號為32(表明B期望收到的下一個報文段的開頭序號為32),視窗為20位元組的確認報文段,那麼A便可以根據這兩個資料構建出如下發送視窗:
傳送視窗1

A傳送11個位元組的資料後,傳送視窗位置不變,可用視窗變小:
傳送視窗2

此時,B收到了前三個位元組,向A傳送確認號為35的確認報文欄位(同時接收視窗向前移動三個位元組);
A的傳送視窗在收到B的確認報文後也向前移動三個位元組。
傳送視窗3

這裡,就需要引入“停止等待”和“累計確認”的概念了:
停止等待”,顧名思義,就是每傳送完一個分組就停止傳送,等待對方的確認。在收到確認後再發送下一個分組。
而在TCP傳輸過程中,為了提高效率、節約資源,採用了“累計確認”的方式:即不必對收到的分組逐個傳送確認,而是對按序到達的最後一個分組傳送確認,表示到這個分組為止的所有分組都已正確收到了

接著,A繼續向B傳送報文,但是B一直沒有發回確認報文。
A在傳送至可用視窗為零時便停止傳送。
傳送視窗4

【後記】
運輸層真的是承上啟下的扛把子,這其中細節還有很多,今天挑了這兩個是因為對於這部分的內容,“直觀上的理解”比“文字上的記憶”更為重要。
TCP的擁塞避免也是個很重要的內容,會出現在下一篇文章中。
最後,你們的反饋就是我最大的動力啦(逃