詳細理解TCP的三次握手以及四次揮手過程,以及常見問題的思考

首先,我們通過一個圖解,來形象表述一下,tcp連接過程的三次握手:

三次握手圖解

1. TCP服務器進程先創建傳輸控制塊TCB,時刻準備接受客戶進程的連接請求,此時服務器就進入了LISTEN(監聽)狀態;

2.  TCP客戶進程也是先創建傳輸控制塊TCB,然後向服務器發出連接請求報文(一個特殊的TCP報文段,該報文段中不包含應用層數據,但是在報文段的首部中的一個標誌位(即SYN比特)被置爲1,因此,這個特殊的報文段被稱爲SYN報文段),由Client發出請求連接即 SYN=1 ACK=0  ,同時隨機選擇一個初始序列號 seq=x ,此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀態。TCP規定,SYN報文段(SYN=1的報文段)不能攜帶數據,但需要消耗掉一個序號。

3. TCP服務器收到請求報文後,如果同意連接,則發出確認報文(有時被稱爲SYNACK報文段)。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要爲自己初始化一個序列號 seq=y,此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據,但是同樣要消耗一個序號。

4. TCP客戶進程收到確認後,還要向服務器給出確認。確認報文的ACK=1,ack=y+1,自己的序列號seq=x+1,此時,TCP連接       建立,客戶端進入ESTABLISHED(已建立連接)狀態。

5. 當服務器收到客戶端的確認後也進入ESTABLISHED狀態,此後雙方就可以開始通信了。

 

三次握手過程中常見問題的思考

1.爲什麼TCP客戶端最後還要發送一次確認呢?

   換句話說,爲什麼tcp連接要進行,三次握手,兩次不行嗎?

建立三次握手主要是因爲A發送了再一次的確認,那麼A爲什麼會再確認一次呢,主要是爲了防止已失效的連接請求報文段又突然傳送給B,從而產生了錯誤。

  所謂“已失效的連接請求報文”是這樣產生的,正常情況下,A發出連接請求,但是因爲連接報文請求丟失而未收到確認,於是A再重傳一次連接請求,後來收到了請求,並收到了確認,建立了連接,數據傳輸完畢後,就釋放鏈接,A共發送了兩次連接請求報文段,其中第一個丟失,第二個到達了B,沒有“已失效的連接請求報文段”,但是還有異常情況下,A發送的請求報文連接段並沒有丟失,而是在某個網絡節點滯留較長時間,以致延誤到請求釋放後的某個時間到達B,本來是一個早已失效的報文段,但是B收到了此失效連接請求報文段後,就誤以爲A又重新發送的連接請求報文段,併發送確認報文段給A,同意建立連接,如果沒有三次握手,那麼B發送確認後,連接就建立了,而此時A沒有發送建立連接的請求報文段,於是不理會B的確認,也不會給B發送數據,而B卻一直等待A發送數據,因此B的許多資源就浪費了,採用三次握手的方式就可以防止這種事情發生,例如剛剛,A不理會B,就不會給B發送確認,B收不到A的確認,就知道A不要求建立連接,就不會白白浪費資源,

 

四次揮手過程圖解

數據傳輸完畢後,雙方都可釋放連接

此圖所示,最開始的時候,客戶端和服務器都是處於ESTABLISHED狀態,然後客戶端主動關閉,服務器被動關閉。

 

1. 客戶端進程發出連接釋放報文,並且停止發送數據。釋放數據報文首部,FIN=1(類似於SYN報文段,其FIN比特被置爲1),其序列號爲seq=u(等於前面已經傳送過來的數據的最後一個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即使不攜帶數據,也要消耗一個序號。

2. 服務器收到連接釋放報文,發出確認報文,ACK=1,ack=u+1,並且帶上自己的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,但是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。

3. 客戶端收到服務器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最後的數據)。

4. 服務器將最後的數據發送完畢後,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由於在剛剛在半關閉狀態的時候,服務器很可能又發送了一些數據,假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。

5. 客戶端收到服務器的連接釋放報文後,必鬚髮出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP連接還沒有釋放,必須經過2∗∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。

6. 服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態。同樣,撤銷TCB後,就結束了這次的TCP連接。可以看到,服務器結束TCP連接的時間要比客戶端早一些。

 

四次揮手過程中常見問題的思考

1.爲什麼客戶端最後還要等待2MSL?

MSL(Maximum Segment Lifetime),最大報文段壽命,TCP允許不同的實現可以設置不同的MSL值。

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

第二,防止類似與“三次握手”中提到了的“已經失效的連接請求報文段”出現在本連接中。客戶端發送完最後一個確認報文後,在這個2MSL時間中,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣新的連接中不會出現舊連接的請求報文。深刻理解一下,這裏所謂的新舊連接的問題:假如沒有這個2msl的等待時間,那麼,此時主動關閉方進入close狀態後,立馬在與另一方(同ip,同端口)進行tcp連接,這時候,新的連接就可能會把之前舊連接所無效的報文段當成自己的報文段,從而產生混亂。

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

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

3.如果已經建立了連接,但是客戶端突然出現故障了怎麼辦?

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

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