TCP詳解之三次握手、四次揮手

在互聯網很多崗位的面試中TCP的三次握手、四次揮手都是不可繞過的話題,有很高的熱點度.今天我就帶大家來看看什麼是三次握手、四次揮手.

在講之前,我們先來了解下TCP協議是什麼

1. TCP協議

TCP協議全稱: 傳輸控制協議, 顧名思義, 就是要對數據的傳輸進行一定的控制.
在這裏插入圖片描述
我們來分析分析每部分的含義和作用

  • 源端口號/目的端口號: 表示數據從哪個進程來, 到哪個進程去.

  • 32位序號:

  • 4位首部長度: 表示該tcp報頭有多少個4字節(32個bit)

  • 6位保留: 顧名思義, 先保留着, 以防萬一

  • 6位標誌位

URG: 標識緊急指針是否有效
ACK: 標識確認序號是否有效
PSH: 用來提示接收端應用程序立刻將數據從tcp緩衝區讀走
RST: 要求重新建立連接. 我們把含有RST標識的報文稱爲復位報文段
SYN: 請求建立連接. 我們把含有SYN標識的報文稱爲同步報文段
FIN: 通知對端, 本端即將關閉. 我們把含有FIN標識的報文稱爲結束報文段

  • 16位窗口大小:
  • 16位檢驗和: 由發送端填充, 檢驗形式有CRC校驗等. 如果接收端校驗不通過, 則認爲數據有問題. 此處的校驗和不光包含TCP首部, 也包含TCP數據部分.
  • 16位緊急指針: 用來標識哪部分數據是緊急數據.
  • 選項和數據暫時忽略

好了,說了TCP協議的基本概念,想必你對TCP的組成有了一點印象,接下來,我們就具體說說什麼是TCP的三次握手、四次揮手.

2.TCP的連接管理機制(三次握手、四次揮手)

正常情況下, TCP需要經過三次握手建立連接, 四次揮手斷開連接.
那麼什麼是三次握手? 什麼是四次揮手呢?

2.1 三次握手

第一次:
客戶端 - - > 服務器 此時服務器知道了客戶端要建立連接了
第二次:
客戶端 < - - 服務器 此時客戶端知道服務器收到連接請求了
第三次:
客戶端 - - > 服務器 此時服務器知道客戶端收到了自己的迴應

到這裏, 就可以認爲客戶端與服務器已經建立了連接.

我們在這上個圖:
在這裏插入圖片描述
剛開始, 客戶端和服務器都處於 CLOSE 狀態.
此時, 客戶端向服務器主動發出連接請求, 服務器被動接受連接請求.

  1. TCP服務器進程先創建傳輸控制塊TCB, 時刻準備接受客戶端進程的連接請求, 此時服務器就進入了 LISTEN(監聽)狀態
  2. TCP客戶端進程也是先創建傳輸控制塊TCB, 然後向服務器發出連接請求報文,此時報文首部中的同步標誌位SYN=1,
    同時選擇一個初始序列號 seq = x, 此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀態。TCP規定,
    SYN報文段(SYN=1的報文段)不能攜帶數據,但需要消耗掉一個序號。
  3. TCP服務器收到請求報文後, 如果同意連接, 則發出確認報文。確認報文中的 ACK=1, SYN=1, 確認序號是 x+1,
    同時也要爲自己初始化一個序列號 seq = y, 此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據, 但是同樣要消耗一個序號。
  4. TCP客戶端進程收到確認後還, 要向服務器給出確認。確認報文的ACK=1,確認序號是 y+1,自己的序列號是 x+1.
  5. 此時,TCP連接建立,客戶端進入ESTABLISHED(已建立連接)狀態。當服務器收到客戶端的確認後也進入ESTABLISHED狀態,此後雙方就可以開始通信了。

一句話簡要概括三次握手:客戶端向服務器端發送SYN包;服務端向客戶端發送SYN+ACK;客戶端回覆ACK。

爲什麼不用兩次?

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

如果採用的是三次握手,就算是那一次失效的報文傳送過來了,服務端接受到了那條失效報文並且回覆了確認報文,但是客戶端不會再次發出確認。由於服務器收不到確認,就知道客戶端並沒有請求連接。

爲什麼不用四次?

因爲三次已經可以滿足需要了, 四次就多餘了.

2.2 四次揮手

話不多說,和三次建立有點類似,直接上圖:
在這裏插入圖片描述

數據傳輸完畢後,雙方都可以釋放連接.
此時客戶端和服務器都是處於ESTABLISHED狀態,然後客戶端主動斷開連接,服務器被動斷開連接.

  1. 客戶端進程發出連接釋放報文,並且停止發送數據
    釋放數據報文首部,FIN=1,其序列號爲seq=u(等於前面已經傳送過來的數據的最後一個字節的序號加1),此時客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即使不攜帶數據,也要消耗一個序號。
  2. 服務器收到連接釋放報文,發出確認報文,ACK=1,確認序號爲u+1,並且帶上自己的序列號seq=v,此時服務端就進入了CLOSE-WAIT(關閉等待)狀態。
    TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
  3. 客戶端收到服務器的確認請求後,此時客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最終數據)
  4. 服務器將最後的數據發送完畢後,就向客戶端發送連接釋放報文,FIN=1,確認序號爲v+1,由於在半關閉狀態,服務器很可能又發送了一些數據,假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。
  5. 客戶端收到服務器的連接釋放報文後,必鬚髮出確認,ACK=1,確認序號爲w+1,而自己的序列號是u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態
  6. 服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB後,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些

爲什麼最後客戶端還要等待 2*MSL的時間呢?

MSL(Maximum Segment Lifetime),TCP允許不同的實現可以設置不同的MSL值。

第一,保證客戶端發送的最後一個ACK報文能夠到達服務器,因爲這個ACK報文可能丟失,站在服務器的角度看來,我已經發送了FIN+ACK報文請求斷開了,客戶端還沒有給我回應,應該是我發送的請求斷開報文它沒有收到,於是服務器又會重新發送一次,而客戶端就能在這個2MSL時間段內收到這個重傳的報文,接着給出迴應報文,並且會重啓2MSL計時器。

第二,防止類似與“三次握手”中提到了的“已經失效的連接請求報文段”出現在本連接中。客戶端發送完最後一個確認報文後,在這個2MSL時間中,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣新的連接中不會出現舊連接的請求報文。

爲什麼建立連接是三次握手,關閉連接卻是四次揮手呢?

建立連接的時候, 服務器在LISTEN狀態下,收到建立連接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。

而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,而自己也未必全部數據都發送給對方了,所以己方可以立即關閉,也可以發送一些數據給對方後,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送,從而導致多了一次。

如果已經建立了連接, 但是客戶端突發故障了怎麼辦?

TCP設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75分鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。

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