TCP系列02—連接管理—1、三次握手與四次揮手


一、TCP連接管理概述 

        正如我們在之前所說TCP是一個面向連接的通信協議,因此在進行數據傳輸前一般需要先建立連接(TFO除外),因此我們首先來介紹TCP的連接管理。

        通常一次完整的TCP數據傳輸一般包含三個階段,分別是連接建立(setup)、數據傳輸(established)和連接釋放(teardown 也稱為cleared 或 terminated)。連接管理部分的主要內容則是TCP連接建立與連接釋放的方式以及TCP連接狀態(connection state)的管理,另外在建立TCP連接的過程中,在發送端和接收端會交換一些選項(option),其中一些選項只能在建立連接的過程中進行交換,有一些則可以在隨后的數據傳輸中進行交換,因此我們也會分別簡單介紹一下這些常見的選項。

        在TCP的連接建立過程中一般需要處理下面三個問題

  1. 要使每一方能夠確知對方的存在。
  2. 要允許雙方協商一些參數(如最大報文段長度,最大窗口大小,服務質量等)。
  3. 能夠對傳輸實體資源(如緩存大小等)進行分配

        TCP建立連接最常見的方式就是通過三次握手(three-way handshake),連接釋放最常見的方式則是四次揮手(four-way handshake或four-way wavehang),下面我們先介紹這兩種最常見的連接管理機制。

 

二、三次握手

        三次握手的整個過程如下圖所示,一般我們稱呼主動發起連接(Active Opener)的一端為客戶端(Client)被動等待連接(Passive Opener)的稱為服務器端(Server)。此處我們說的客戶端和服務器端和我們在WEB開發中使用客戶端和服務器端的概念略有差異,WEB開發中一般稱呼用戶側為客戶端,后台為服務器端,但是后台的服務器端也可以主動向客戶端發起TCP連接(盡管這種場景少一些),這個時候后台服務器也就相當於我們下圖中的客戶端了。

 

d

 

下面我們介紹一下整個過程

  • A和B的初始狀態都是關閉狀態,B進入LISTEN狀態后被動打開,此時B等待接收客戶端的SYN包建立連接。
  • A主動打開時,A 的 TCP 向 B 發出連接請求報文段,其首部中的同步位 SYN = 1,選擇序號 seq = x,表明傳送報文時的第一個字節序號是 x,由於SYN標志在邏輯上占用一個系列號,因此實際數據傳輸的時候,TCP傳輸的數據中第一個Byte對應的系列號為x+1。這個SYN包發送以后,A則進入SYN_SENT狀態,等待B回復ACK確認包。
  • B 的 TCP 收到連接請求報文段后,則發回確認。B 在確認報文段中應使 SYN = 1,使標志位 ACK = 1, 其確認號ack = x + 1,自己選擇的序號 seq = y。記得我們之前說過序列號SN實際代表傳輸了多少比特的數據凈荷,實際上在TCP的SYN包中一般並不攜帶數據,但是由於SYN包和FIN包在協議規定在邏輯上面占1個Byte,因此B在接收到這個SYN包后回復的ack=x + 1。后面我們會講到消耗系列號SN就意味着這個數據包一旦丟失可以進行重傳操作,由於SYN消耗一個byte的系列號,因此SYN數據包丟失的時候是會觸發重傳的。在B收到A的SYN包並且發送ACK確認包后,B則進入SYN_RCVD狀態。
  • A 收到此報文段后向 B 給出確認,其 ACK = 1,確認號 ack = y + 1。此時A進入ESTABLISHED狀態,A 的 TCP 通知上層應用進程,連接已經建立。   
  • B 的 TCP 收到主機 A 的確認后,B也進入ESTABLISHED狀態,同時通知其上層應用進程當前TCP 連接已經建立。

一般來說上面用來建立連接的初始系列號ISN(即x和y)的值是隨機選取的,后面的文章會簡單介紹ISN的生成。

 

三、四次揮手

        數據傳輸結束后,通信的雙方都可釋放連接。現在如下圖假設A 的應用進程先向其 TCP 發出連接釋放報文段,並停止發送數據,主動關閉 TCP連接。則四次揮手的過程如下圖所示

 

四次揮手釋放連接的流程如下

  • 初始狀態下A和B都是處於ESTABLISHED狀態,當應用層沒有待發數據而指示A關閉TCP連接的時候,A 設置連接釋放報文段首部的標志位 FIN = 1,ACK=1,其序號seq = u,確認號ack=v,等待 B 的確認。此時A進入FIN_WAIT_1狀態
  • B 收到A的FIN包的時候,發出確認,由於FIN包與SYN包類似都在邏輯上占1byte,因此確認號 ack = u + 1,而這個報文段自己的序號 seq = v。此時B進入CLOSE_WAIT狀態,TCP 服務器進程通知高層應用進程。
  • 當A收到B的ACK確認包后,A進入FIN_WAIT_2狀態,關於這個狀態我們后續在進一步介紹。   
  • 若 B 已經沒有要向 A 發送的數據,其應用進程就通知 TCP 釋放連接。B 設置連接釋放報文首部的FIN=1,ACK=1,報文序列號seq=v,確認號ack=u+1。此時B進入LAST_ACK狀態。 
  • A 收到連接釋放報文段后,必須發出確認,在確認報文段中 ACK = 1,確認號 ack = v + 1,自己的序號 seq = u +1。 此時A進入TIME_WAIT狀態。在TIME_WAIT狀態下,A經過2MSL時間后就進入關閉狀態,關於TIME_WAIT狀態我們后續進一步介紹。
  • 在B接收到A的確認包后,B立即進入關閉狀態。A和B都進入關閉狀態后整個TCP連接釋放。

四、三次揮手

        在四次揮手關閉TCP連接的時候,有時會省略第二條ACK消息,只存在第一條FIN消息、第三條FIN+ACK消息以及第四條FIN消息,從上圖四次揮手的過程中可以看到其實第二條消息的ACK Number和第三條消息的ACK Number是相同的,省略第二條的時候其實是第三條消息捎帶了第二條消息的ACK,后面完整介紹TCP的狀態機的時候,會看到這種省略第二條消息的狀態消息。

五、wireshark抓包

        對於上面講到的三次握手和四次揮手,通過wireshark抓包來觀察一下

 

 

        其中進行連接的兩個socket(還記得我們前面章節說過一個ip地址+一個端口構成一個socket,或者叫做endpoint吧),一個是127.0.0.1:49324,對應我們前面示意圖中的active opener和active closer,另外一個socket是127.0.0.1:9877,則對應passive opener和passive closer。注意wireshark中的系列號Seq呈現的是相對值,所以第一條消息會呈現Seq=0,實際值為0xbc069a3b。wireshark圖中[SYN, ACK]表示TCP頭中SYN標志位和ACK標志位有效,[SYN]、[FIN, ACK]等含義類似。將wireshark中SYN、FIN兩個標志位,以及系列號Seq、應答號Ack與前面的示意圖對應起來觀察一下吧。

        對於三次揮手的情況,wireshark抓包如下為了使兩端的seq更容易區分,三次握手后我從client端向server端傳輸了10bytes數據,如下圖高亮的條目所示,傳輸10bytes后進行三次揮手的TCP連接終止的過程

 

 

補充說明

1.TCP連接的建立和終止可以參考RFC793協議

2.第二版<TCP/IP Illustrated Volume1>中給出的四次揮手過程中最后一條消息的seq是錯誤的

 

 

 

 

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM