TCP“三次報文握手,四次報文揮手”詳解
TCP 的基本認識
TCP 中文又被稱之為傳輸控制協議,它是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。這個特性的解釋如下:
- 面向連接的:面向連接也就是說一對一才能連接。
- 可靠的:無論網絡中出現了什么變化,TCP都能保證一個報文一定能夠到達接收端
- 字節流:消息是沒有邊界的,所以無論消息有多大都可以進行傳輸
學習過網絡的朋友就知道,對于一個協議來說,往往會分成多個層,層與層之間解耦,對于 TCP 傳輸控制層協議來講,它也是這樣的,下面是 TCP 協議的一個結構示意圖:
可以看到,TCP 的應用層就對應著 OSI 參考模型的應用層、表示層、會話層,傳輸層和網絡層是一一對應的,然后緊接著是網絡接口層,網絡接口層對應著 OSI參考模型的 數據鏈路層、物理層。在說了 TCP/IP 的分層模型,緊接著來介紹下 TCP 的頭部格式,它的頭部格式如下所示:
上圖就是針對于 TCP 頭部的一個示意圖,下面對于幾個概念進行解釋:
- 序列號:用來解決網絡的亂序問題
- 確認應答號:指下一次期望收到的數據的序列號,用來解決不丟包的問題
- 控制位:
- ACK: 該位為 1 時,確認應答的字段變為有效,TCP規定除了最初建立連接時的 SYN 包之外該位必須設置為 1
- RST:該位為 1 時,表示 TCP 連接中出現異常必須強制斷開連接
- SYN: 該位為 1 時,表示期望建立連接,并在其序列號的字段進行序列號初始值的設定
- FIN :該位為 1 時,表示今后不再有數據發送,希望斷開連接。
那對于 TCP 來說,什么叫做連接呢,什么樣子才說是兩臺設備已經連接起來了呢?簡單來說,也就是用于保證可靠性和流量控制維護的某些狀態信息,這些信息的組合,包括 Socket、序列號和窗口大小稱之為連接。那么 TCP 建立一個連接,那么就需要客戶端和服務器端達成一個共識,共識的內容就包括:
- Socket:由 IP 地址和端口號組成
- 序列號:用來解決亂序問題
- 窗口大小:用來做流量控制
那么又該如何確定一個連接呢?就是說是哪臺設備中的哪個進程與哪臺設備中哪個進程進行通信,需要如下幾個信息:
- 源地址
- 源端口號
- 目標地址
- 目標端口號
TCP 的運輸連接
在前文中敘述了 TCP 是面向連接的協議,它是基于傳輸連接來傳送 TCP 報文段,TCP 傳輸連接的建立和釋放是每一次面向連接的通信中必不可少的過程,TCP 的運輸連接主要有以下三個階段:
- 建立 TCP 連接
- 數據傳送
- 釋放 TCP 連接
上述就是 TCP 運輸連接的一個基本過程,基于此,我們來依次對這幾種過程進行剖析。
TCP 建立連接
TCP 建立連接要解決的是以下三個問題:
- 使得 TCP 雙方能夠確知對方的存在;
- 使得 TCP 雙方能夠協商一些參數(如最大窗口值、是否使用窗口擴大選項和時間戳選項以及服務質量等);
- 使得 TCP 雙方能夠對運輸實體資源(如緩存大小、連接表中的項目等)進行分配
那么建立連接的過程主要如下圖所示:
根據上圖所示,我們可以看到 TCP 建立連接時的一個基本流程:
首先,TCP服務器進程首先創建傳輸控制塊,用來傳輸 TCP 連接中的一些重要信息:TCP連接表,指向發送和接收緩存的指針,指向重傳隊列的指針,當前發送和接收序號等等。。。之后呢,準備接受TCP客戶進程的連接請求,此時,TCP服務進程就進入監聽狀態,等待 TCP 進程的連接請求,需要注意的是作為 TCP 服務端,這里是被動打開連接。
其次,對應著第一個箭頭,SYN=1,seq=x。TCP 客戶端進程首先創建傳輸控制塊,然后,在打算建立連接時,向TCP服務器進程發送TCP連接請求報文段,并進入同步已經發送狀態。TCP連接請求報文段首部中的同步位SYN被設置為1,也就表明這是一個 TCP 連接請求報文段,序號字段 seq 被設置了一個初始值,作為 TCP 客戶進程所選擇的初始序號,(這里要注意的是:TCP規定 SYN 設置為 1 的報文段不能夠攜帶數據 ,但是要消耗掉一個序號,由于 TCP 連接建立是由 TCP 客戶端主動發起的,因此稱之為主動打開連接)
緊接著,對應著第二個箭頭,SYN=1 ACK=1 seq=y ack=x+1。TCP 服務端如果同意客戶端建立連接,則向 TCP 客戶端進程發送 TCP 連接請求確認報文段,并進入同步已經接收狀態
最后,TCP 客戶端收到連接請求確認報文段之后,還需要向 TCP 服務進程發送一個普通的 TCP 確認報文段,并進入連接已建立狀態。該報文是 ACK=1 seq=x+1 ack=y+1,也就表明這是一個普通的 TCP 確認報文段。(普通的 TCP 確認報文段可以攜帶數據,但是如果說當前的 TCP 確認報文段不攜帶數據,那么也就不消耗數據報文段的序號,也就是說下一個數據報文段的序號還是 x+1),當 TCP 服務端收到這個普通認報文段之后,TCP服務端也進入連接已建立狀態,這時 TCP 客戶端和 TCP 服務端都進入了連接已經建立狀態,就可以開始傳輸數據了。
上述就是一個三次報文握手建立連接的一個過程,那么分析到這里,就出現了一個問題,就是說當 TCP 服務端發送連接請求確認報文段之后,當 TCP 客戶端收到這個報文,難么就進入連接已建立狀態了,這個時候直接發送數據不就行了,為什么還要再次發送一個 TCP 普通確認報文段呢?這是為什么?
要解釋這個問題,那首先假設當前 TCP 建立連接采用的是兩報文握手連接,那么在 TCP 客戶端發送連接請求報文段之后,TCP 服務器接收到連接請求報文段就進入連接已經建立狀態,進一步 TCP 服務端發送連接請求確認報文段,這個時候,TCP 客戶端收到報文之后,就也進入連接已經建立狀態。然后,基于此,我們來看下面這樣一個情況:
如上圖所示,由于 TCP 客戶端發送的第一個連接請求報文段沒有能夠成功發送出去,TCP 服務端沒有能夠接收到這個報文段,這個時候,TCP客戶端又重新發起了一個連接請求報文段,依據剛剛所說的過程,TCP 服務器在接收到這個報文段之后,就進入了連接已經建立狀態,緊接著,客戶端也進入了連接已經建立狀態,就可以進行數據傳輸了,但是,這個時候,由于之前的 TCP 連接請求報文發送失敗,導致的超時重傳,在TCP已經釋放連接的時候,TCP 客戶端收到連接請求報文段,進入連接已經建立狀態,但是這個時候對于 TCP 客戶端來說,它已經關閉連接了,無法進入連接已經建立狀態,這樣也就會導致 TCP 服務器白白的在干等,在浪費資源。
這也就是為什么采用三次報文握手,而不采用兩次報文握手的原因。
TCP 釋放連接
數據傳輸完畢之后,TCP雙方都可以釋放連接,現在 TCP 客戶進程和 TCP 服務進程都處于連接已建立狀態,如果使用 TCP 客戶進程中的應用進程通知其主動關閉 TCP 連接,TCP 客戶進程會發送 TCP 連接釋放報文段,并進入終止等待1狀態。發送的報文稱之為是 TCP 釋放報文段,這里需要注意的是 FIN == 1 的報文段即使不攜帶數據,也要消耗掉一個序號。
當 TCP 服務端收到來自 TCP 客戶端的釋放報文段的時候,會發送一個普通的 TCP 確認報文段并進入關閉等待狀態,具體過程如下圖所示:
這個時候,TCP 服務段進程要通知高層應用進程TCP客戶端要斷開與自己的連接,這個時候 TCP 客戶端的連接已經斷開了,也就是 TCP 客戶進程已經沒有數據要發送了,但是TCP 服務器進程如果還有數據要發送,TCP 客戶進程仍然要接收,那么也就是說從 TCP 服務進程到 TCP 客戶進程這個反向的連接還沒有關閉,這個狀態可能會持續一段時間,當前的 TCP 連接處于半斷開連接。
當 TCP 客戶端進程收到來自TCP服務端進程的確認報文段之后,就進入終止等待 2 狀態,等待 TCP 服務器進程發出的 TCP 連接釋放報文段,如果處在 TCP 服務器中的應用進程已經沒有數據要發送了,那么應用進程就通知 TCP 服務器進程釋放連接,TCP 服務器進程發送 TCP 連接釋放報文段并進入最后確認狀態。
在 TCP 客戶端進程接收到 TCP 服務端進程的連接釋放報文段之后,必須針對該報文段發送普通的 TCP 確認報文段,之后進入時間等待狀態:
在 TCP 服務器進程收到TCP客戶端進程發送過來的普通TCP確認報文段之后,就進入關閉狀態,而對于 TCP 客戶端來說,需要經過 2MSL 之后才關閉連接。
其中 MSL 為最長報文壽命。那說到這里,又出現一個問題,也就是說當 TCP 客戶端發送 TCP 普通確認報文段之后,為什么不直接就進入關閉狀態,而是還需要等待 2MSL 呢,有這個必要么,為了解決這個問題,我們來看如下的解釋,比如說當前就不需要進行等待了,具體通信過程如下圖所示:
就是說,當 TCP 服務器進程往 TCP 客戶端進程發送釋放連接報文段的時候,在 TCP 客戶端接受到這個報文,轉而 TCP 客戶端發送普通確認報文,但是這個報文就丟失了,而此時 TCP 客戶端進程已經斷開連接,無法再次發送普通確認報文,TCP 服務端進程沒有收到普通確認報文,那么就無法進入關閉狀態,就會抑制超時重傳 TCP 連接釋放報文,出現問題。
綜上所述,也就是說 TCP 客戶端等待 2MSL 的時間是為了能夠使得 TCP 服務器端進程能夠收到最后一個 TCP 確認報文段而進入關閉狀態 。對于另外一個原因,等待 2MSL 才關閉也能夠使得本次連接持續時間內所產生的所有報文段都從網絡中消失,這樣就可以使得笑一個 TCP 連接中,不會出現舊連接的報文段。以上就是 TCP 通過“四報文揮手”釋放連接的過程。
小結
上述就是關于 TCP 運輸連接的一個基本內容闡述,詳細論述了 TCP 三次報文揮手建立連接以及四次報文揮手釋放連接的詳細過程,當然 TCP 還有其他內容,剩下的下一期再進行闡述吧~
本文轉載自微信公眾號「wenzi嵌入式軟件」,可以通過以下二維碼關注。轉載本文請聯系wenzi嵌入式軟件公眾號。