繞不開的TCP之三次握手

在面試過程中,無論是開發還是測試崗位,TCP都是一個繞不開的話題,而談到TCP,大概率三次握手也會被提及,那應該如何回答這個問題呢?在回答這個問題之前,讓我們先預熱一波吧。

TCP的定義

TCP協議全稱: 傳輸控制協議, 顧名思義, 就是要對數據的傳輸進行一定的控制,它是一種面向連接的、可靠的、基於字節流的傳輸層通信協議。

TCP連接全過程的狀態

TCP連接全過程中,客戶端及服務端存在的狀態如下:

  • LISTEN:偵聽來自遠方的TCP端口的連接請求(服務器)
  • SYN-SENT:在發送連接請求後等待匹配的連接請求(客戶端)
  • SYN-RCVD:在收到和發送一個連接請求後等待對方對連接請求的確認(服務器)
  • ESTABLISHED:代表一個打開的連接(客戶端、服務器)
  • FIN-WAIT-1:等待遠程TCP連接中斷請求,或先前的連接中斷請求的確認(客戶端)
  • FIN-WAIT-2:從遠程TCP等待連接中斷請求(客戶端)
  • CLOSE-WAIT:等待從本地用戶發來的連接中斷請求(服務器)
  • CLOSING:等待遠程TCP對連接中斷的確認(客戶端、服務器)
  • LAST-ACK:等待原來的發向遠程TCP的連接中斷請求的確認(服務器
  • TIME-WAIT:等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認(客戶端)
  • CLOSED:沒有任何連接狀態(客戶端、服務器)

TCP的3次握手

TCP的連接建立和連接關閉,都是通過請求-響應的模式完成的。TCP採用3次握手建立連接的過程如下(整個過程可以採用wireshark進行抓包獲取)。

注意, 客戶端和服務器起始狀態都處於 CLOSE 狀態。

  1. TCP服務器進程先創建傳輸控制塊TCB, 時刻準備接受客戶端進程的連接請求, 此時服務器就進入了 LISTEN(監聽)狀態。
  2. TCP客戶端進程也是先創建傳輸控制塊TCB, 然後向服務器發出連接請求報文,此時報文首部中的同步標誌位SYN=1, 同時選擇一個初始序列號 seq = x(x爲隨機生成), 此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀態。TCP規定, SYN報文段(SYN=1的報文段)不能攜帶數據,但需要消耗掉一個序號。
  3. TCP服務器收到請求報文後, 如果同意連接, 則發出確認報文。確認報文中的 ACK=1, SYN=1, 確認序號是 x+1(x爲第2步客戶端發送過來的序列號), 同時也要爲自己初始化一個序列號 seq = y(y爲隨機生成), 此時, TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據, 但是同樣要消耗一個序號。
  4. TCP客戶端進程收到服務端回覆後需要進行相關確認(該處需要檢查第3步服務器發送的標誌位ACK的值是否爲1,確認序號是否爲第2步客戶端發送的初始序號x+1),當確認正確後,還要向服務器給出確認。確認報文的ACK=1,確認序號是 y+1,自己的序列號是 x+1。
  5. 此時,TCP連接建立,客戶端進入ESTABLISHED(已建立連接)狀態。當服務器收到客戶端的確認後也進入ESTABLISHED狀態,此後雙方就可以開始通信了。
    接下來讓我們以圖片的形式再展示一下3次握手的整個流程。
    在這裏插入圖片描述

上面提到的SYN、ACK等標誌位,它們分別代表什麼含義呢?

SYN表示建立連接,ACK表示響應,除了這兩個標誌位外,常用的還有FIN(表示關閉連接)、PSH(表示有數據傳輸)和RST(表示連接重置)。

PS:ACK、SYN和FIN這些大寫的單詞表示標誌位,其值要麼是1,要麼是0;ack、seq小寫的單詞表示序號。

其中,ACK是可能與SYN,FIN等同時使用的,比如SYN和ACK可能同時爲1,它表示的就是建立連接之後的響應,如果只是一個SYN,它表示的只是建立連接。TCP的幾次握手就是通過這樣的ACK表現出來的。但SYN與FIN是不會同時爲1的,因爲前者表示的是建立連接,而後者表示的是斷開連接。

RST一般是在FIN之後纔會出現爲1的情況,表示的是連接重置。當出現FIN包或RST包時,可以認爲客戶端與服務器端斷開了連接;而當出現SYN和SYN+ACK包時,則可以認爲客戶端與服務器建立了一個連接。PSH爲1的情況,一般只出現在 DATA內容不爲0的包中,也就是說PSH爲1表示的是有真正的TCP數據包內容被傳遞。

讀到這裏,好奇的小夥伴可能會問,爲什麼TCP連接是3次握手呢?爲什麼不是2次握手或者4次握手呢?讓我們一起來尋根究底,探尋一下原因吧。

爲什麼不用兩次?主要是爲了防止已經失效的連接請求報文突然又傳送到了服務器,從而不必要的錯誤。可以假設這樣一種場景,客戶端發送的第一個請求連接沒有丟失,而是延遲到達,由於TCP的客戶端在超時時間內沒有收到服務器的確認報文,以爲服務器沒有收到,此時會重新向服務器發送這條報文,這時客戶端和服務器在經過兩次握手完成連接並傳輸數據後關閉了連接。然後之前滯留的那一次請求連接,因爲網絡通暢到達了服務器,這個報文本該是失效的,但是,兩次握手的機制將會讓客戶端和服務器再次建立連接,這將導致不必要的錯誤和資源浪費。
而如果採用的是三次握手,即使前面一次失效的報文又傳送過來了,服務端接受到了那條失效報文並且回覆了確認報文,但是客戶端不會再次發出確認。由於服務器收不到確認,就可以知道客戶端並沒有請求連接,該次報文請求是失效的。

那爲什麼不用四次?這時因爲三次已經可以滿足需要了, 四次就多餘了,而多餘就意味着資源的浪費,自然而然應該被摒棄了。

其他文章可以關注微信公衆號測試架構師養成記,還有資料可以領哦~
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章