位元組一面:說說TCP的三次握手

  • 2022 年 8 月 28 日
  • 筆記

上周有朋友去了位元組面試,問到了TCP三次握手的問題,當時回答的不是很好,對於三次握手的發送的報文資訊都不太熟,本文主要做一下總結和記錄。

TCP全稱為Transmission Control Protocol(傳輸控制協議),是一種面向連接的、可靠的、基於位元組流的傳輸層通訊協議。TCP也是全雙工通訊協議,表示客戶端可以給服務端發送消息,服務端也可以向客戶端發送消息。

報文

TCP處於ISO七層模型的傳輸層,傳輸層的單位是報文,報文資訊如下:

Source port 和 Destination port

其中Source portDestination port分別代表發送埠接收埠。兩個不同機器上的進程通訊,需要通過和IP協議中的IP標識唯一的進程。

Sequence number 和 Acknowledgment number

Sequence number表示序列號,表示要發送數據的起始號,在下面的三次握手使用seq表示,Acknowledgment number表示確認號,返回確認號,表示消息已經接收,返回下次要發送的起始號。在下面的三次握手使用ackNum標識。

TCP flag

TCP flag表示TCP標誌位,主要介紹兩個ACKSYN

  • SYN同步序號,用於建立連接過程。
  • ACK確認序號標識,標識表示發送資訊已確認接收。

Windows Size

TCP使用滑動窗口來實現流量控制,根據窗口大小,確認要發送數據包的個數。

TCP 三次握手

TCP三次握手,是指建立一個TCP連接時,需要客戶端和伺服器總共發送3個包。三次握手的目的是連接服務指定埠,建立 TCP 連接,並確認連接雙方的序列號確認號,確認TCP窗口大小資訊。

三次握手詳解:

  • 第一次握手 SYN=1,seq=x
    • 客戶端發送一個TCPSYN標誌位為1的包,指定客戶端連接的伺服器埠,初始序列號seqx。發送完畢之後客戶端進入SYN_SEND
  • 第二次握手 SYN=1,ACK=1,seq=y,ACKnum=x+1
    • 伺服器發回確認包ACK應答。即SYN標誌位和ACK標誌位均為1。伺服器端發送序列號seqy,同時將確認序號ackNum設置為客戶端的序列號seq+1ackNum表示要下次要發送數據包序列號的起始值。發送完畢後,服務端進入SYN_SEND狀態。
  • 第三次握手 ACK=1,ACKnum=y+1
    • 客戶端再次發送確認包ACK,ACK 標誌位為1,並且把伺服器發來的ackNum作為起始序號seq發送給服務端,確認號ackNum為服務端發送的序列號+1也就是y+1,放在確認欄位中發送給對方,
    • 發送完畢後,客戶端進入ESTABLISHED狀態,當伺服器端接收到這個包時,也進入ESTABLISHED狀態,開始數據傳輸。

wireshake 抓包

為了更好理解三次握手,使用wireshakej進行抓包。首先請求訪問鏈接,TCP三次握手對應下面編號576364:

  • 第一步:192.168.5.150 —-> 47.98.202.133 [SYN] seq=0
  • 第二步:47.98.202.133 —-> 192.168.5.150 [SYN ACK] seq=0 ack=1
  • 第三步:192.168.3.150 —-> 47.98.202.133 [ACK] seq=1 ack=1

記憶口訣

那麼在面試的時候應該如何記憶三次握手的流程?三次握手是為了建立連接,其中主要是為了確認客戶端和服務端的序列號seq,那麼確認序列號就需要接收方返回序列號,來確保自己發送的序列號能成功發送。

  • 第一次握手和第二次握手確保客戶端的序列號,所以第一次發送seq,第二次返回ack,當接收到返回資訊,表明確認了客戶端序列號。第一次和第二次都是建立連接過程,所以都帶有SYN標記位。而第二次返回號,所以第二次帶ACK標誌位。
  • 第一次發送了序號seqx,返回確認號ackNumx+1,因為發送消耗了一個序號,所以ackNum要加1
  • 第二次握手和第三次握手是為了確保服務端的序列號,服務端發送序列號seq,客戶端返回確認號ackNum,值為seq+1。第二次握手要發送序號和返回上一次的握手的確認號,所以第二次握手帶有SYNACK標誌位。並且要發送序列號seq和確認號ackNum。第三次握手是確認服務端發送序列號,所以帶有標誌位ACK,返回確認號ackNum

為啥 TCP 需要三次握手,不是兩次,四次

TCP三次握手是為了確認雙方的序列號,這就像一個發送—應答機制,客戶端發序列號,服務端返回確認號,此時確認了客戶端的序列號。如果是兩次握手,只能確認客戶端的序列號,無法確認服務端的序列號。三次握手是確認兩個序列號最小的連接次數。四次也可以,但是沒有必要,需要減少握手的次數,加快連接速度。

總結

  • 本文先介紹了報文頭資訊,三次握手主要用到了:
    • 序列號seq,確認號ackNum
    • TCP標記位,SYN同步序號,表示建立連接過程。ACK確認序號標識,標識表示發送資訊已確認接收
  • 三次握手詳解:
    • 第一次握手,客戶端發送帶有SYN標記位的包,帶有初始化序列號x,發送完畢客戶端進入SYN_SEND狀態。
    • 第二次握手,服務端返回應答標記位ACK,並返回確認號ackNumx+1,x+1表示發送消耗了一個序列號。返回了確認號表示確認了客戶端序列號。服務端也要發送序列號y,所以也要帶有SYN的標記位。
    • 第三次握手客戶端發送確認包ackNumy+1,所以帶確認序號標誌ACK。建立連接,發送序號x+1,開始傳輸數據。

參考

TCP協議