TCP連線的關鍵之謎:揭秘三次握手的必要性

努力的小雨發表於2023-09-22

TCP 連線建立

當我們瀏覽網頁、傳送電子郵件或者進行線上遊戲時,我們常常不會想到背後複雜的網路連線過程。然而,正是這些看似不起眼的步驟,確保了我們與伺服器之間的穩定通訊。其中最重要的步驟之一就是TCP連線的建立,而其中的核心環節就是三次握手。

本文將詳細探討三次握手的原理、過程以及其重要性。我們將一步步解析為什麼需要三次握手,它如何保證連線的穩定性和可靠性,以及它對於資料傳輸的重要作用。透過深入理解三次握手,我們將更好地理解網路通訊的底層機制,並對TCP連線的可靠性有更清晰的認識。

TCP 三次握手過程和狀態變遷

TCP是一種面向連線的傳輸層協議,它在進行資料傳輸之前需要先建立連線。這個連線的建立過程是透過三次握手來完成的。

image

我們根據這幅圖詳細講解,每次連線中所傳送的TCP報文。

在最開始,客戶端和服務端都處於CLOSED狀態。首先,服務端主動監聽某個埠,處於LISTEN狀態,即伺服器必須處於啟動狀態。接下來,客戶端準備開始訪問網頁,需要與伺服器建立連線。第一次連線報文的格式如下:

image

客戶端在發起連線時,會隨機生成一個初始序號(client_isn),並將其放置在TCP首部的"序號"欄位中。同時,客戶端將SYN標誌位置為1,表示發出的報文是SYN報文。客戶端透過傳送第一個SYN報文給服務端,表明它希望與服務端建立連線。該報文不包含應用層資料(也就是傳送的資料)。此時,客戶端的狀態被標記為SYN-SENT。

image

當服務端收到客戶端的SYN報文時,首先服務端會隨機初始化自己的序號(server_isn),然後將該序號填入TCP首部的"序號"欄位中。接著,服務端將"確認應答號"欄位填入client_isn + 1,並將SYN和ACK標誌位都設定為1。最後,服務端將該報文傳送給客戶端,該報文不包含應用層資料(此時伺服器也沒資料可發)。此時,服務端處於SYN-RCVD狀態。

image

一旦客戶端收到服務端的報文,它需要做以下最佳化來回應最後一個應答報文:首先,客戶端將該應答報文的TCP首部的ACK標誌位設定為1;其次,客戶端在"確認應答號"欄位中填入server_isn + 1的值;最後,客戶端將報文傳送給服務端。此次報文可以攜帶客戶端到伺服器的資料。完成這些操作後,客戶端將進入ESTABLISHED狀態。

一旦伺服器收到客戶端的應答報文,它也會切換到 ESTABLISHED 狀態。

從上面的過程可以發現,在進行三次握手時,第三次握手是可以攜帶資料的,而前兩次握手則不可以。這也是面試中經常被問到的問題。一旦完成三次握手,雙方都會進入ESTABLISHED狀態,表示連線已經成功建立,此時客戶端和服務端就可以開始相互傳送資料了。

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

相信大家通常回答的是:“因為三次握手才能保證雙方具有接收和傳送的能力。”這個回答沒錯,但它只是表面上的原因,並沒有提出主要的原因。下面我將從三個方面分析三次握手的原因,加深我們對這個問題的理解。

  • 三次握手可以有效地避免歷史重複連線的初始化(主要原因)
  • 三次握手可以保證雙方都收到了可靠的初始序列號。
  • 三次握手可以避免資源浪費。

原因一:避免歷史重複連線

簡單來說,三次握手的主要原因是為了避免舊的重複連線初始化造成混亂。在複雜的網路環境中,資料包的傳輸並不總是按照規定時間傳送到達目標主機,可能會因為網路擁堵等原因導致舊的資料包先到達目標主機。為了避免這種情況,TCP使用三次握手的方式來建立連線。

image

當客戶端連續傳送多個SYN建立連線的報文時,在網路擁堵等情況下,可能會出現以下情況:

  • 舊的SYN報文比最新的SYN報文先到達服務端。
  • 服務端收到舊的SYN報文後會回覆一個SYN + ACK報文給客戶端。
  • 客戶端收到SYN + ACK報文後,根據自身的上下文判斷這是一個歷史連線(序列號過期或超時),然後傳送RST報文給服務端,表示中止這次連線。

如果是兩次握手的連線方式,就無法判斷當前連線是否是歷史連線。而三次握手可以在客戶端準備傳送第三次報文時,根據上下文判斷當前連線是否是歷史連線:

  • 如果是歷史連線(序列號過期或超時),則第三次握手傳送的報文是RST報文,以中止歷史連線。
  • 如果不是歷史連線,則第三次傳送的報文是ACK報文,通訊雙方成功建立連線。

因此,TCP使用三次握手的主要原因是為了防止歷史連線初始化了連線。

原因二:同步雙方初始序列號

TCP協議的通訊雙方都必須維護一個序列號,這是確保可靠傳輸的關鍵因素。序列號在TCP連線中扮演了重要角色,它具有以下作用:

● 接收方可以消除重複的資料,確保資料的準確性。

● 接收方可以按照序列號的順序接收資料包,保證資料的完整性。

● 序列號可以標識已經被對方接收的資料包,實現可靠的資料傳輸。

因此,在建立TCP連線時,客戶端傳送帶有初始序列號的SYN報文,並需要伺服器回覆一個ACK報文,表示成功接收了客戶端的SYN報文。然後,伺服器傳送帶有初始序列號的SYN報文給客戶端,並等待客戶端的應答,這樣一來一回,才能確保雙方的初始序列號能夠可靠地同步。

image

雖然四次握手也可以實現可靠地同步雙方的初始序列號,但由於第二步和第三步可以合併為一步,所以最終演變成了三次握手。而兩次握手只能保證一方的初始序列號被對方成功接收,無法保證雙方的初始序列號都能被確認接收。因此,三次握手是為了確保TCP連線的穩定性和可靠性而採取的最佳選擇。

原因三:避免資源浪費

如果只有"兩次握手"的話,當客戶端的SYN請求在網路中被阻塞時,客戶端無法接收到伺服器傳送的ACK報文,因此會重新傳送SYN。然而,由於沒有第三次握手,伺服器無法確定客戶端是否收到了建立連線的ACK確認訊號。因此,伺服器只能在收到每個SYN請求後主動建立一個連線。這將導致以下情況的發生:

資源浪費:如果客戶端的SYN請求被阻塞,導致重複傳送多個SYN報文,伺服器在收到請求後將建立多個冗餘的無效連線。這將導致伺服器資源的不必要浪費。

訊息滯留:由於缺乏第三次握手,伺服器無法知道客戶端是否正確接收到了建立連線的ACK確認訊號。因此,如果訊息在網路中出現滯留,客戶端將一直重複傳送SYN請求,導致伺服器不斷建立新的連線。這將增加網路擁塞和延遲,並對整個網路效能產生負面影響。

image

因此,為了確保網路連線的穩定性和可靠性,TCP使用了三次握手來建立連線,以避免以上問題的發生。

總結

TCP連線建立是透過三次握手來完成的。在三次握手過程中,客戶端首先傳送一個帶有SYN標誌的報文給伺服器,表示希望建立連線。伺服器接收到客戶端的請求後,回覆一個帶有SYN和ACK標誌的報文給客戶端,表示接受連線請求,併傳送自己的初始序列號。最後,客戶端再回復一個帶有ACK標誌的報文給伺服器,表示連線建立成功。這樣,雙方就進入了ESTABLISHED狀態,可以開始相互傳送資料。

總的來說,TCP連線建立的三次握手過程是為了確保連線的穩定性和可靠性,避免歷史連線的混亂和資源浪費,同時保證雙方都具備接收和傳送資料的能力。

相關文章