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

  「三次握手」,參考:http://www.javashuo.com/article/p-ycpsakky-nt.htmlhtml


 

  前面進行「三次握手」創建鏈接後,當客戶端的數據發送完畢,它就會要求與服務器端斷開鏈接,那麼就要進行「四次揮手」進行鏈接的釋放。服務器

  注意,此處所謂的「客戶端」與「服務器端」,只是爲了方便標識鏈接的雙方,即確認哪一方是「要求斷開鏈接」的主動方,哪一方是「要求斷開鏈接」的被動方。事實上任何一方均可能在發送完數據後要求與另外一方斷開鏈接。網絡

一、「四次揮手」過程spa

  以下圖:htm

 

 

 

 

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

1)「第一次揮手」:首先,客戶端已經發送完數據,想要釋放鏈接(客戶端是釋放鏈接的主動方),向服務器端發送一段TCP報文,其中:資源

  i)標記位 FIN=1:表示這個TCP請求是「請求釋放鏈接」;get

  ii)報文的序號 seq=u:u 等於前面客戶端已經傳送的數據的最後一個字節的序號加1;it

  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;

  iii)確認號 ack=u+1:仍是但願客戶端下一次發送的報文序號爲 u+1;

  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」 鏈接關閉狀態。

總結:後「兩次揮手」既讓客戶端知道了服務器端準備好釋放鏈接了,也讓服務器端知道了客戶端了解了本身準備好釋放鏈接了。因而,能夠確認關閉服務器端端到客戶端方向上的鏈接了,由此完成「四次揮手」,關閉了鏈接。

 

二、三個關鍵問題

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個探測報文客戶端仍然沒反應,服務器端就認爲客戶端出了故障,接着就關閉鏈接。

相關文章
相關標籤/搜索