TCP協議「三次握手」與「四次揮手」詳解(下)

2022-08-03 01:18:13 字數 3593 閱讀 3357

「三次握手」,參考:

前面進行「三次握手」建立連線後,當客戶端的資料傳送完畢,它就會要求與伺服器端斷開連線,那麼就要進行「四次揮手」進行連線的釋放。

注意,此處所謂的「客戶端」與「伺服器端」,只是為了方便標識連線的雙方,即確認哪一方是「要求斷開連線」的主動方,哪一方是「要求斷開連線」的被動方。事實上任何一方都可能在傳送完資料後要求與另一方斷開連線。

1、「四次揮手」過程

如下圖:

「四次揮手」的具體過程如下:

1)「第一次揮手」:首先,客戶端已經傳送完資料,想要釋放連線(客戶端是釋放連線的主動方),向伺服器端傳送一段tcp報文,其中:

i)標記位 fin=1:表示這個tcp請求是「請求釋放連線」;

ii)報文的序號 seq=u:u 等於前面客戶端已經傳送的資料的最後乙個位元組的序號加1;

iii)客戶端由「established」連線建立狀態,進入「fin-wait-1」終止等待狀態1。此時客戶端不會再向伺服器端傳送資料。

需要注意,fin報文雖然不攜帶資料,但是但是它會消耗乙個位元組序號。即客戶端第一次傳送的fin報文 seq=u,報文會消耗乙個序號,那麼客戶端下次傳送的報文應該從 seq=u+1 開始傳送。

2)「第二次揮手」:伺服器端接收到從客戶端發出的tcp報文之後,確認了客戶端想要釋放連線,會傳送回乙個tcp報文,其中:

i)標記位為ack=1:表示「伺服器端告知客戶端,自己已經接收到客戶端傳送的釋放連線的請求」;

ii)報文序號 seq=v:伺服器端到客戶端的連線還沒有關閉,伺服器端還會向客戶端傳送資料報,這個報文序號為 v;

iii)確認號ack = u+1:表示希望客戶端下乙個報文的序號是 u+1,即希望客戶端下乙個報文從序號為 u+1 的位元組開始傳送。我們知道客戶端第乙個報文 seq=u,且該報文為fin報文,佔乙個序號,那麼客戶端下乙個報文就應該從 u+1 開始傳送。

iv)伺服器端結束 「established」 連線階段,進入「close-wait」 關閉等待狀態;

此時從 客戶端到伺服器端 這個方向的連線就被釋放,tcp連線處於「半關閉狀態」 。 此時客戶端不會再向伺服器端傳送資料,但是伺服器端可能還會想客戶端傳送資料。

v)客戶端收到從伺服器端發出的tcp報文之後,確認了伺服器端收到了客戶端發出的釋放連線請求,隨後客戶端結束「fin-wait-1」終止等待狀態1,進入「fin-wait-2」終止等待狀態2。

總結:前兩次揮手,既讓伺服器端知道了客戶端想要釋放連線,也讓客戶端知道了伺服器端知道了自己想要釋放連線。

3)「第三次揮手」:客戶端經過 「close-wait」 關閉等待 狀態後,它要傳送給伺服器端的資料也傳送完畢,即它做好了釋放伺服器端到客戶端連線的準備,就會想客戶端傳送一段fin的tcp報文:

i)標記位 fin=1,ack=1:表示「伺服器端告知客戶端,自己已經做好釋放連線的準備」;

ii)報文序號 seq=w:關閉等待階段,伺服器端可能又向客戶端傳送了資料,因此此時 seq 不是v,而是最新的資料 w;

iv)傳送「第三次揮手」報文後,伺服器端進入「last-ack」 最後確認階段。此後,伺服器端再也無法向客戶端傳送資料。

注意,第三次揮手傳送的是fin的報文,沒有資料但是會佔乙個序號,即下一次伺服器端傳送的報文序號 seq=w+1。

4)「第四次揮手」:客戶端接收到伺服器端「第三次揮手」的報文後,確認伺服器端已經做好斷開連線的準備,會向客戶端傳送「第四次握手」的報文:

i)標記位ack=1:表示「客戶端已經知道伺服器端做好釋放連線的準備」;

ii)ack = w+1:將收到伺服器端報文的 seq+1,作為自己的ack。表示希望伺服器端下次傳送的報文的序號為 w+1;

iii)seq=u+1:將收到伺服器端報文的 ack 作為自己的 seq,因為伺服器端報文 ack=u+1 表示希望客戶端這次傳送的報文序號是 u+1,那麼客戶端這次傳送報文的序號就設定為 u+1;

iv)客戶端傳送完第四次揮手的報文後,啟動等待計時器,等待2msl後,如果沒有收到伺服器端新的請求,就進入「closed」 連線關閉狀態;

v)伺服器端在收到客戶端傳送的第四次揮手的報文後,進入進入「closed」 連線關閉狀態。

總結:後「兩次揮手」既讓客戶端知道了伺服器端準備好釋放連線了,也讓伺服器端知道了客戶端了解了自己準備好釋放連線了。於是,可以確認關閉伺服器端端到客戶端方向上的連線了,由此完成「四次揮手」,關閉了連線。

2、三個關鍵問題

1)為什麼「握手」是三次,而「揮手」卻是四次?

對於「三次握手」,在第二次握手的時候,伺服器端向客戶端傳送的報文的標記位包含 syn=1以及ack=1,syn是請求連線標誌,表示伺服器端同意建立連線;ack是確認報文,表示告訴客戶端,伺服器端收到了它的請求報文。即「確認接收」與「同意連線」是在同一次握手中傳輸的。那麼通過三次握手就剛剛好可以建立連線;

對於「四次揮手」,第二次揮手的時候,伺服器端可能還沒有做好關閉連線的準備(它可能還有資料要傳送給客戶端),因此,它不會立即釋放連線,會在第二次揮手先返回乙個ack=1,表示已經接受到客戶端的斷開連線的請求。隨後,客戶端處理完資料後,會傳送第三次揮手報文,其中fin=1,表示伺服器端已經準備好釋放連線。因此,釋放連線需要經過「四次揮手」。

2)為什麼客戶端要在傳送第四次揮手的報文後等待2msl的時間才進入closed狀態?

目的是為了確認伺服器端會收到客戶端傳送的「第四次揮手」的ack確認報文。

msl(max segment lifetime): 最長報文段壽命,也就是乙個報文在網路中存活的最長時間,一般設定為2分鐘。當客戶端發出最後的ack確認報文時,並不能確定伺服器端能夠收到該段報文。所以客戶端在傳送完ack確認報文之後,會設定乙個時長為2msl的計時器。

在1msl的時候,如果伺服器端沒有收到客戶端傳送的ack確認報文,就會再次向客戶端傳送fin報文,這個報文在1msl的時間內會到達客戶端,此時客戶端邊知道自己上一次傳送的ack確認報文沒有傳送到伺服器端,於是客戶端會再次向伺服器端傳送ack確認報文,並將等待計時器重置。

如果在2msl的時間內沒有接受到伺服器端傳送回來的fin報文,說明客戶端最後傳送的ack確認報文已經被伺服器端接收到,可以關閉連線。因此,事實上客戶端會比伺服器端更晚進入closed狀態。

3)如果已經建立了連線,但是客戶端出現故障了怎麼辦?

如果客戶端傳送錯誤,伺服器端還一直保持連線,這個連線並不會傳送資料,並且占用了伺服器端的資源。伺服器端有乙個「保活計時器」,伺服器端每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設定為2小時,若2小時還沒有收到客戶端的任何資料,客戶端就會傳送乙個探測報文段,以後每隔75秒鐘傳送一次。若一連傳送10個探測報文客戶端仍然沒反應,伺服器端就認為客戶端出了故障,接著就關閉連線。

TCP三次握手與四次揮手協議

tcp 在不可靠的網路通道傳進行可靠的訊息傳輸 1 tcp首部資訊 2 三次握手 syn synchronrous 同步訊息序列,發起乙個新的連線 tcp三次握手過程中,攜帶syn 同步序號 seq 訊息序號 rwd 視窗大小 1 urg 緊急指標 urgent pointer 有效。2 ack 確...

TCP協議三次握手與四次揮手

其實該過程就像一次打 前去拜訪 1 客戶端 喂?伺服器麼,我今天要去拜訪你。syn 1 seq x 2 伺服器 哦,好的,我去門口接你。syn 1 ack 1 seq y ack x 1 3 客戶端 我到了,你真客氣,我要進來了。ack 1 seq x 1 ack y 1 客戶端主動開啟,伺服器被動...

TCP協議,三次握手與四次揮手

tcp報文格式 每行簡介 1.源埠和目的埠各佔2個位元組,即16位。2.32位序號,佔4個位元組,tcp連線中傳送的位元組流中每個位元組都按順序編號。例如,一段報文的序號字段值是 301 而攜帶的資料共有100欄位,顯然下乙個報文段 如果還有的話 的資料序號應該從401開始。3.32位確認序號。是期...