TCP建立連接爲什麼需要三次握手,而斷開連接則需要四次?

一、TCP建立連接的過程

在這裏插入圖片描述

1. 第一次握手

客戶端向服務器發出連接請求報文,這時報文首部中的同部位SYN=1,同時隨機生成初始序列號 seq=x

此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀態。TCP規定,SYN報文段(SYN=1的報文段)不能攜帶數據,但需要消耗掉一個序號

這個三次握手中的開始。表示客戶端想要和服務端建立連接。

2. 第二次握手

TCP服務器收到請求報文後,如果同意連接,則發出確認報文。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要爲自己隨機初始化一個序列號 seq=y

此時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據,但是同樣要消耗一個序號。這個報文帶有SYN(建立連接)和ACK(確認)標誌,詢問客戶端是否準備好

3. 第三次握手

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

TCP規定,ACK報文段可以攜帶數據,但是如果不攜帶數據則不消耗序號。這裏客戶端表示我已經準備好


二、TCP建立連接爲什麼需要三次握手?

解釋1:

  1. 發起連接方發出SYN,並收到ACK,這就是兩次網絡傳輸了。
  2. 同樣被連接方也發出SYN,且等待對方回覆,這也是兩次網絡傳輸。
  3. 加起來難道不是四次嗎?實際上被連接方將對連接方 SYN(1) 的回覆和自己 SYN(1) 的請求合併了,所以建立一個 TCP 連接最少只需要經過三次網絡傳輸

解釋2:
舉例:已失效的連接請求報文段

  1. client發送了第一個連接的請求報文,但是由於網絡不好,這個請求沒有立即到達服務端,而是在某個網絡節點中滯留了,直到某個時間纔到達server。
    本來這已經是一個失效的報文,但是server端接收到這個請求報文後,還是會想client發出確認的報文,表示同意連接
  2. 假如不採用三次握手,那麼只要server發出確認,新的建立就連接了,但其實這個請求是失效的請求,client是不會理睬server的確認信息,也不會向服務端發送確認的請求。但是server認爲新的連接已經建立起來了,並一直等待client發來數據,這樣,server的很多資源就沒白白浪費掉了。
  3. 採用三次握手就是爲了防止這種情況的發生,server會因爲收不到確認的報文,就知道client並沒有建立連接。這就是三次握手的作用。

三、TCP斷開連接的過程

在這裏插入圖片描述

1. 第一次揮手

TCP發送一個FIN(結束),用來關閉客戶到服務端的連接。客戶端進程發出連接釋放報文,並且停止發送數據。

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

2. 第二次揮手

服務端收到這個FIN,他發回一個ACK(確認),確認收到序號爲收到序號+1,和SYN一樣,一個FIN將佔用一個序號。

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

這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。

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

3. 第三次揮手

服務端發送一個FIN(結束)到客戶端,服務端關閉客戶端的連接

服務器將最後的數據發送完畢後,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由於在半關閉狀態,服務器很可能又發送了一些數據

假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。

4. 第四次揮手

客戶端發送ACK(確認)報文確認,並將確認的序號+1,這樣關閉完成。

客戶端收到服務器的連接釋放報文後,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。

注意此時TCP連接還沒有釋放,必須經過2∗∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。

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


四、TCP斷開連接爲什麼需要四次揮手?

解釋1:

  1. 發起斷開方發出FIN,並收到ACK,這就是兩次網絡傳輸了。
  2. 同樣被斷開方也發出FIN,且等待對方回覆,這也是兩次網絡傳輸。
  3. 同樣的邏輯分析下來,實際上也可以僅經過三次傳輸就斷開此次連接,但爲什麼我們會說四次揮手呢?這是因爲如果在收到FIN時,彼時還有數據未傳輸完,則先回復關於 FIN 的 ACK,告知對方我已經知道你要斷開了。則等待傳輸完畢後,被斷開方再發送 FIN,告知自己也已經可以斷開連接
  4. 但實際上完全可以是“三次揮手”,如果收到 FIN 時,已經沒有數據要傳輸,則是“三次揮手”。

解釋2:
爲了確保數據能夠完成傳輸

  1. 關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了。所以你未必會馬上關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的
  2. 可能有人會有疑問,tcp我握手的時候爲何ACK(確認)和SYN(建立連接)是一起發送。揮手的時候爲什麼是分開的時候發送呢?
  3. 因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。
  4. 但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉 SOCKET,所以只能先回復一個ACK報文,告訴Client端,“你發的FIN報文我收到了”。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步揮手。

五、斷開連接時客戶端突然掛掉了怎麼辦?

正常連接時,客戶端突然掛掉了,如果沒有措施處理這種情況,那麼就會出現客戶端和服務器端出現長時期的空閒

解決辦法是在服務器端設置保活計時器每當服務器收到客戶端的消息,就將計時器復位。超時時間通常設置爲2小時

若服務器超過2小時沒收到客戶的信息,他就發送探測報文段。若發送了10個探測報文段,每一個相隔75秒,還沒有響應就認爲客戶端出了故障,因而終止該連接。


參考文章:

  1. 馬士兵公衆號的一篇文章
  2. TCP爲啥要3次握手和4次揮手?握兩次手不行嗎?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章