天天看點

一文講清楚TCP的三次握手四次揮手

0. 前言

在面試中,計算機網絡的 TCP 三次握手和四次揮手是很常見的問題,但是在實際面試中,面試官會更願意聽到怎樣的回答呢?詳細程度是怎樣的?越簡單常見的問題越不可小觑,萬丈高樓平地起,把簡單的問題深入化,才更能拉開與競争者的距離。掌握了本文講的全部知識點,關于 TCP 三次握手和四次揮手基本就 OK 了 😊

1. TCP 和 UDP

講解 TCP 三次握手和四次握手之前,我們先了解一下 TCP 和 UDP 這兩個重量級的傳輸層協定。

💦 使用者資料報協定 UDP(User Datagram Pro

目錄

​​1. TCP 和 UDP​​

​​2. TCP 封包段首部格式​​

​​3. TCP 三次握手建立連接配接​​

​​① 三次握手過程詳解​​

​​② 為什麼要三次握手​​

​​③ ISN (Initial Sequence Number) 是固定的嗎​​

​​④ 三次握手過程中可以攜帶資料嗎​​

​​⑤ 半連接配接隊列​​

​​⑥ SYN 洪泛攻擊​​

​​⑦ 如果第三次握手丢失了,用戶端服務端會如何處理​​

​​4. TCP 四次揮手釋放連接配接​​

​​① 四次揮手過程詳解​​

​​② 為什麼要四次揮手​​

tocol):

  • UDP 在傳送資料之前不需要先建立連接配接,遠端主機在收到 UDP 封包後,不需要給出任何确認。
  • 雖然 UDP不提供可靠傳遞,但在某些情況下 UDP 确是一種最有效的工作方式(一般用于即時通信),比如:

    QQ 語音、 QQ 視訊 、直播等等

💦 傳輸控制協定 TCP(Transmission Control Protocol):

  • TCP 提供面向連接配接的服務。

    在傳送資料之前必須先建立連接配接,資料傳送結束後要釋放連接配接。

  • TCP 不提供廣播或多點傳播服務。由于 TCP 要提供可靠的,面向連接配接的傳輸服務(TCP的可靠展現在TCP在傳遞資料之前,會有三次握手來建立連接配接,而且在資料傳遞時,有确認、視窗、重傳、流量控制、擁塞控制機制,在資料傳完後,還會四次揮手斷開連接配接用來節約系統資源),這不僅使協定資料單元的首部增大很多,還要占用許多處理機資源。
  • TCP一般用于檔案傳輸、發送和接收郵件、遠端登入等場景。

2. TCP 封包段首部格式

TCP 封包段的具體格式大家可以不必都記住,但是其中的幾個控制位與我們接下來要講的三次握手和四次揮手息息相關,大家一定要牢記。

一文講清楚TCP的三次握手四次揮手

首部固定部分各字段意義如下:

  • 1 -源端口和目的端口:各占 2 個位元組,分别寫入源端口和目的端口。IP 位址 + 端口号就可以确定一個程序位址
  • 2 -序号/序列号(Sequense Number,SN):在一個 TCP 連接配接中傳送的位元組流中的每一個位元組都按順序編号。該字段表示本封包段所發送的資料的第一個位元組的序号。初始序号稱為 Init Sequense Number, ISN(序号/序列号這個字段很重要,大家留個印象,下文會詳細講解)

    例如,一封包段的序号是 101,共有 100 位元組的資料。這就表明:本封包段的資料的第一個位元組的序号是 101,最後一個位元組的序号是 200。顯然,下一個封包段的資料序号應當從 201 開始,即下一個封包段的序号字段值應為 201。

  • 3 - 确認号 ack:期望收到對方下一個封包段的第一個資料位元組的序号。若确認号為 N,則表明:到序号 N-1 為止的所有資料都已正确收到。
  • 4 -資料偏移(首部長度):它指出 TCP 封包段的資料起始處距離 TCP 封包段的起始處有多遠。這個字段實際上是指出TCP封包段的首部長度。
  • 5 -保留:占 6 位,應置為 0,保留為今後使用。

⭐ 大家看上圖,保留位的右邊還有 6 個控制位(重要),這是TCP 用來說明該封包段性質的:

  • 緊急位 URG:當 URG = 1 時,表明此封包段中有緊急資料,是高優先級的資料,應盡快發送,不用在緩存中排隊。該控制位需配合緊急指針使用(緊急指針指出本封包段中緊急資料的位元組數)

    舉個例子:我們需要取消一個已經發送了很長程式的運作,是以使用者從鍵盤發出中斷指令。如果不使用緊急資料,那麼這個指令将存儲在接收 TCP 的緩存末尾,隻有在所有的資料被處理完畢後這兩個字元才被傳遞接收方的應用程序,這樣做就無法實作立即中斷。

  • 确認 ACK:僅當 ACK = 1 時确認号字段才有效,當 ACK = 0 時确認号無效。TCP 規定,在連接配接建立後所有傳送的封包段都必須把 ACK 置為 1。
  • 推送 PSH:當兩個應用程序進行互動式的通信時,有時在一端的應用程序希望在鍵入一個指令後立即就能收到對方的響應。在這種情況下,TCP 就可以使用推送(push)操作。這時,發送方 TCP 把 PSH 置為 1,并立即建立一個封包段發送出去。接收方 TCP 收到 PSH = 1 的封包段,就盡快地傳遞接收應用程序。而不用等到整個緩存都填滿了後再向上傳遞。
  • 複位 RST:當 RST = 1 時,表明 TCP 連接配接中出現了嚴重錯誤(如由于主機崩潰或其他原因),必須釋放連接配接,然後再重建立立傳輸連接配接。
  • 同步 SYN:SYN = 1 表示這是一個連接配接請求或連接配接接受封包。

    當 SYN = 1 而 ACK = 0 時,表明這是一個連接配接請求封包段。對方若同意建立連接配接,則應在響應的封包段中使 SYN = 1 且 ACK = 1。

  • 終止 FIN:用來釋放一個連接配接。當 FIN = 1時,表明此封包段的發送發的資料已發送完畢,并要求釋放運輸連接配接。

3. TCP 三次握手建立連接配接

① 三次握手過程詳解

三次握手的原文是 ​

​three-way handshake​

​,整個名詞的可以翻譯為:需要三個步驟才能建立握手/連接配接的機制。當然,三次握手也可以叫 ​

​three-message handshake​

​,通過三條消息來建立的握手/連接配接。進行三次握手的主要作用就是為了确認雙方的接收能力和發送能力是否正常、指定自己的 初始化序列号(Init Sequense Number,  ​

​ISN​

​) 為後面的可靠性傳輸做準備。

三次握手過程如下圖:

一文講清楚TCP的三次握手四次揮手

回顧一下圖中字元的含義:

  • ​SYN​

    ​:連接配接請求/接收 封包段
  • ​seq​

    ​:發送的第一個位元組的序号
  • ​ACK​

    ​:确認封包段
  • ​ack​

    ​:确認号。希望收到的下一個資料的第一個位元組的序号

剛開始用戶端處于 ​

​Closed​

​ 的狀态,而服務端處于 ​

​Listen​

​ 狀态:

​CLOSED​

​:沒有任何連接配接狀态

​LISTEN​

​:偵聽來自遠方 TCP 端口的連接配接請求

1)第一次握手:用戶端向服務端發送一個 SYN 封包(SYN = 1),并指明用戶端的初始化序列号 ISN(x),即圖中的 seq = x,表示本封包段所發送的資料的第一個位元組的序号。此時用戶端處于 ​

​SYN_Send​

​ 狀态。

​SYN-SENT​

​ :在發送連接配接請求後等待比對的連接配接請求

2)第二次握手:伺服器收到用戶端的 SYN 封包之後,會發送 SYN 封包作為應答(SYN = 1),并且指定自己的初始化序列号 ISN(y),即圖中的 seq = y。同時會把用戶端的 ISN + 1 作為确認号 ack 的值,表示已經收到了用戶端發來的的 SYN 封包,希望收到的下一個資料的第一個位元組的序号是 x + 1,此時伺服器處于 ​

​SYN_REVD​

​ 的狀态。

​SYN-RECEIVED​

​:在收到和發送一個連接配接請求後等待對連接配接請求的确認

3)第三次握手:用戶端收到伺服器端響應的 SYN 封包之後,會發送一個 ACK 封包,也是一樣把伺服器的 ISN + 1 作為 ack 的值,表示已經收到了服務端發來的的 SYN 封包,希望收到的下一個資料的第一個位元組的序号是 y + 1,并指明此時用戶端的序列号 seq = x + 1(初始為 seq = x,是以第二個封包段要 +1),此時用戶端處于 ​

​Establised​

​ 狀态。

伺服器收到 ACK 封包之後,也處于 ​

​Establised 狀态​

​,至此,雙方建立起了 TCP 連接配接。

​ESTABLISHED​

​:代表一個打開的連接配接,資料可以傳送給使用者

② 為什麼要三次握手

三次握手的目的是建立可靠的通信信道,說到通訊,簡單來說就是資料的發送與接收,而三次握手最主要的目的就是雙方确認自己與對方的發送與接收是正常的。

隻有經過三次握手才能确認雙發的收發功能都正常,缺一不可:

  • 第一次握手(用戶端發送 SYN 封包給伺服器,伺服器接收該封包):

    用戶端什麼都不能确認;伺服器确認了對方發送正常,自己接收正常

  • 第二次握手(伺服器響應 SYN 封包給用戶端,用戶端接收該封包):

    用戶端确認了:自己發送、接收正常,對方發送、接收正常;

    伺服器确認了:對方發送正常,自己接收正常

  • 第三次握手(用戶端發送 ACK 封包給伺服器):

    用戶端确認了:自己發送、接收正常,對方發送、接收正常;

    伺服器确認了:自己發送、接收正常,對方發送、接收正常

③ ISN (Initial Sequence Number) 是固定的嗎

三次握手的其中一個重要功能是用戶端和服務端交換 ISN(Initial Sequence Number),以便讓對方知道接下來接收資料的時候如何按序列号組裝資料。

當一端為建立連接配接而發送它的 SYN 時,它會為連接配接選擇一個初始序号。ISN 随時間而變化,是以每個連接配接都将具有不同的 ISN。如果 ISN 是固定的,攻擊者很容易猜出後續的确認号,是以 ISN 是動态生成的。

④ 三次握手過程中可以攜帶資料嗎

第三次握手的時候,是可以攜帶資料的。但是,第一次、第二次握手絕對不可以攜帶資料

假如第一次握手可以攜帶資料的話,如果有人要惡意攻擊伺服器,那他每次都在第一次握手中的 SYN 封包中放入大量的資料,然後瘋狂重複發 SYN 封包的話(因為攻擊者根本就不用管伺服器的接收、發送能力是否正常,它就是要攻擊你),這會讓伺服器花費很多時間、記憶體空間來接收這些封包。

⭐ 簡單的記憶就是,請求連接配接/接收即 ​

​SYN = 1​

​ 的時候不能攜帶資料

而對于第三次的話,此時用戶端已經處于 ​

​ESTABLISHED​

​ 狀态。對于用戶端來說,他已經建立起連接配接了,并且也已經知道伺服器的接收、發送能力是正常的了,是以當然能正常發送/攜帶資料了。

⑤ 半連接配接隊列

伺服器第一次收到用戶端的 SYN 之後,就會處于 ​

​SYN_RCVD​

​ 狀态,此時雙方還沒有完全建立其連接配接,伺服器會把這種狀态下的請求連接配接放在一個隊列裡,我們把這種隊列稱之為半連接配接隊列。

當然還有一個全連接配接隊列,完成三次握手後建立起的連接配接就會放在全連接配接隊列中。如果隊列滿了就有可能會出現丢包現象。

⑥ SYN 洪泛攻擊

SYN 攻擊就是 Client 在短時間内僞造大量不存在的 IP 位址,并向 Server 不斷地發送 SYN 包,Server 則回複确認包,并等待 Client 确認,由于源位址不存在,是以 Server 需要不斷重發直至逾時,這些僞造的 SYN 包将長時間占用半連接配接隊列,導緻正常的 SYN 請求因為隊列滿而被丢棄,進而引起網絡擁塞甚至系統癱瘓。

⑦ 如果第三次握手丢失了,用戶端服務端會如何處理

伺服器發送完 SYN-ACK 包,如果未收到用戶端響應的确認包,也即第三次握手丢失。那麼伺服器就會進行首次重傳,若等待一段時間仍未收到客戶确認包,就進行第二次重傳。如果重傳次數超過系統規定的最大重傳次數,則系統将該連接配接資訊從半連接配接隊列中删除。

注意,每次重傳等待的時間不一定相同,一般會是指數增長,例如間隔時間為 1s,2s,4s,8s…

4. TCP 四次揮手釋放連接配接

① 四次揮手過程詳解

建立一個 TCP 連接配接需要三次握手,而終止一個 TCP 連接配接要經過四次揮手(也有将四次揮手叫做四次握手的)。這是由于 TCP 的半關閉(half-close)特性造成的,TCP 提供了連接配接的一端在結束它的發送後還能接收來自另一端資料的能力。

TCP 連接配接的釋放需要發送四個包(執行四個步驟),是以稱為四次揮手(​

​Four-way handshake​

​),用戶端或服務端均可主動發起揮手動作。

一文講清楚TCP的三次握手四次揮手

回顧一下上圖中符号的意思:

  • ​FIN​

    ​ :連接配接終止位
  • ​seq​

    ​:發送的第一個位元組的序号
  • ​ACK​

    ​:确認封包段
  • ​ack​

    ​:确認号。希望收到的下一個資料的第一個位元組的序号

剛開始雙方都處于​

​ESTABLISHED​

​ 狀态,假設是用戶端先發起關閉請求。四次揮手的過程如下:

1)第一次揮手:用戶端發送一個 FIN 封包(請求連接配接終止:FIN = 1),封包中會指定一個序列号 seq = u。并停止再發送資料,主動關閉 TCP 連接配接。此時用戶端處于 ​

​FIN_WAIT1​

​ 狀态,等待服務端的确認。

​FIN-WAIT-1​

​ - 等待遠端TCP的連接配接中斷請求,或先前的連接配接中斷請求的确認;

2)第二次揮手:服務端收到 FIN 之後,會發送 ACK 封包,且把用戶端的序号值 +1 作為 ACK 封包的序列号值,表明已經收到用戶端的封包了,此時服務端處于 ​

​CLOSE_WAIT​

​ 狀态。

​CLOSE-WAIT​

​ - 等待從本地使用者發來的連接配接中斷請求;

此時的 TCP 處于半關閉狀态,用戶端到服務端的連接配接釋放。用戶端收到服務端的确認後,進入​

​FIN_WAIT2​

​(終止等待 2)狀态,等待服務端發出的連接配接釋放封包段。

​FIN-WAIT-2​

​ - 從遠端TCP等待連接配接中斷請求;

3)第三次揮手:如果服務端也想斷開連接配接了(沒有要向用戶端發出的資料),和用戶端的第一次揮手一樣,發送 FIN 封包,且指定一個序列号。此時服務端處于 ​

​LAST_ACK​

​ 的狀态,等待用戶端的确認。

​LAST-ACK​

​ - 等待原來發向遠端TCP的連接配接中斷請求的确認;

4)第四次揮手:用戶端收到 FIN 之後,一樣發送一個 ACK 封包作為應答(ack = w+1),且把服務端的序列值 +1 作為自己 ACK 封包的序号值(seq=u+1),此時用戶端處于 ​

​TIME_WAIT​

​ (時間等待)狀态。

​TIME-WAIT​

​ - 等待足夠的時間以確定遠端TCP接收到連接配接中斷請求的确認;

🚨 注意 !!!這個時候由服務端到用戶端的 TCP 連接配接并未釋放掉,需要經過時間等待計時器設定的時間 2MSL(一個封包的來回時間)後才會進入 ​

​CLOSED​

​ 狀态(這樣做的目的是確定服務端收到自己的 ACK 封包。如果服務端在規定時間内沒有收到用戶端發來的 ACK 封包的話,服務端會重新發送 FIN 封包給用戶端,用戶端再次收到 FIN 封包之後,就知道之前的 ACK 封包丢失了,然後再次發送 ACK 封包給服務端)。服務端收到 ACK 封包之後,就關閉連接配接了,處于 ​

​CLOSED​

​ 狀态。

② 為什麼要四次揮手

由于 TCP 的半關閉(half-close)特性,TCP 提供了連接配接的一端在結束它的發送後還能接收來自另一端資料的能力。

繼續閱讀