自己理解的TCP三次握手

海山了-發表於2024-07-12

### TCP 三次握手過程是怎樣的?

TCP的建立連線是透過三次握手來進行的。三次握手的過程如下圖:

image-20240711211752851

說實話這個很好理解,我稱之為N字型

首先我們理解到建立連線是一個虛的概念了對吧?那麼我們來設計一個可靠的TCP,首先建立連線是必須的吧?相當於我們打電話,總要先說一句喂---wei?(面向連線正是這個意思!)

那麼這裡順便談談他們很愛問的一個問題

為什麼是三次握手?不是兩次、四次?

首先你(客戶端)要和我(服務端)打電話,我們再要說出內容時,都需要先確定下,網路如何?對方能否聽到吧?

而上圖中藍色的SYN相當於就是問候伺服器能否聽到,然後伺服器的ACK對應的就是我能聽到,

而這裡我們說的"我能聽到"在現實中對映到TCP中就代表著ACK而且是SYN,因為接下來對方會回覆你說"好"或者說"原本要和你說的內容"也即是綠色的ACK

然後兩次的話,是必然不可行的,雙方都確認對方能接收資訊才能說這個連線建立成功,那麼能準確證明兩個不行嗎?首先要雙方都確認必然要2SYN和2ACK,那麼很明顯兩個ACK的分配,要麼(1,1),要麼(2,0)這裡2,0可以順序相反,(2,0)意味著單方發出兩個ACK必然不行!(1,1)意味著雙方都發ack,那麼必然在時間上有交錯,因為同時發的話,這個ack就沒用了,ack有用的前提是收到syn後再發,同時時間交錯則也只能保障單次ack生效,在前發的ack無效

所以證畢,至少三次握手

那麼四次可行嗎?肯定可以啊,不談那些不太荒唐的,你把server的ack和syn拆分後就可以了,只不過比較浪費頻寬

到此如果要實現上述功能我們只需要SYN和ACK便夠了,那麼又為何帶上SeqNum呢?以及ACK的時候要對應的+1呢?僅僅是說對暗號的情況嗎?因為我們計算機會維持多個tcp連線,透過這個來知道他對應的是哪個連線嗎?是的,但是僅此而已嗎?

所以更深層上三次握手還能實現其他功能:

  • 三次握手才可以阻止重複歷史連線的初始化(主要原因)
  • 三次握手才可以同步雙方的初始序列號
  • 三次握手才可以避免資源浪費
阻止歷史連線的初始化

下面是小林的解釋,我來用我自己的話,來讓自己更好地瞭解,首先情況是服務端seqNum為90的這個報文傳送後,重啟了那麼又重新想向服務端建立連線,所以發了個新的seqNum為100,如果90的報文仍然到達了服務端,那麼服務端會再傳送90對應的90+1的ACK+SYN,那麼這時你客戶端不就可以確認了嗎?你就會弄一個RST位為1的報文,給服務端,效果類似說"打錯了",然後之後100的服務端會再傳送100+1,

同理我們這個"N"的下一個折角處也是可以防止服務端重啟後,這個SYN+ACK導致的歷史連結的問題

三次握手避免歷史連線

然後值得注意的一點是,如果服務端收到客戶端報文的順序是:「舊 SYN 報文」->「新 SYN 報文」

那麼服務端並不是說同樣地給這個返回RST,因為誰是挑戰者不好說!對他來講90可能是新的也可能是舊的,100同樣,所以他採用的是認定先來的

所以他返回的是ChangeACK報文給客戶端,這個 ack 報文並不是確認收到「新 SYN 報文」的,而是上一次的 ack 確認號,也就是91(90+1)。說白了,解玲還需繫鈴人,所以這個RST報文只能由他們的原先傳送者確認是否結束

同步雙方初始序列號
  • 接收方可以去除重複的資料;
  • 接收方可以根據資料包的序列號按序接收;
  • 可以標識傳送出去的資料包中, 哪些是已經被對方收到的(透過 ACK 報文中的序列號知道);

序列號在 TCP 連線中佔據著非常重要的作用,所以當客戶端傳送攜帶「初始序列號」的 SYN 報文的時候,需要服務端回一個 ACK 應答報文,表示客戶端的 SYN 報文已被服務端成功接收,那當服務端傳送「初始序列號」給客戶端的時候,依然也要得到客戶端的應答回應,這樣一來一回,才能確保雙方的初始序列號能被可靠的同步。

避免資源浪費

如果只有「兩次握手」,當客戶端發生的 SYN 報文在網路中阻塞,客戶端沒有接收到 ACK 報文,就會重新傳送 SYN由於沒有第三次握手,服務端不清楚客戶端是否收到了自己回覆的 ACK 報文,所以服務端每收到一個 SYN 就只能先主動建立一個連線

如果客戶端傳送的 SYN 報文在網路中阻塞了,重複傳送多次 SYN 報文,那麼服務端在收到請求後就會建立多個冗餘的無效連結,造成不必要的資源浪費。

相關文章