面試官:跟我講講TCP的三次握手和四次揮手流程,爲什麼是三次握手或四次揮手?

面試者:額......不太記得了.....gg..

在前面的文章知道, 《TCP與UDP的區別 ,到 《TCP是如何保證可靠性 。那麼接下來就是TCP的核心了,即TCP的可靠性依賴其:三次握手和四次揮手。

先思考下這三個面試題:

1、TCP 爲什麼三次握手而不是兩次握手?

2、爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?

3、爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

在TCP/IP協議中,TCP協議提供可靠的連接服務,連接是通過三次握手進行初始化的。三次握手的目的是同步連接雙方的序列號和確認號並交換 TCP窗口大小信息。

tcp三次握手和四次揮手交互圖:

三次握手:

  1. 第一次握手:建立連接。客戶端發送連接請求報文段,將 SYN 位置爲1, Sequence Number 爲x;然後,客戶端進入 SYN_SEND 狀態,等待服務器的確認;

  2. 第二次握手:服務器收到 SYN 報文段。服務器收到客戶端的 SYN 報文段,需要對這個 SYN 報文段進行確認,設置 Acknowledgment Number 爲x+1( Sequence Number +1);同時,自己自己還要發送 SYN 請求信息,將 SYN 位置爲1, Sequence Number 爲y;服務器端將上述所有信息放到一個報文段(即 SYN+ACK 報文段)中,一併發送給客戶端,此時服務器進入 SYN_RECV 狀態;

  3. 第三次握手:客戶端收到服務器的 SYN+ACK 報文段。然後將 Acknowledgment Number 設置爲y+1,向服務器發送 ACK 報文段,這個報文段發送完畢以後,客戶端和服務器端都進入 ESTABLISHED 狀態,完成TCP三次握手。

四次揮手:

  1. 第一次揮手:主機1(可以使客戶端,也可以是服務器端),設置 Sequence Number Acknowledgment Number ,向主機2發送一個 FIN 報文段;此時,主機1進入 FIN_WAIT_1 狀態;這表示主機1沒有數據要發送給主機2了;

  2. 第二次 揮手 :主機2收到了主機1發送的 FIN 報文段,向主機1回一個 ACK 報文段, Acknowledgment Number Sequence Number 加1;主機1進入 FIN_WAIT_2 狀態;主機2告訴主機1,我“同意”你的關閉請求;

  3. 第三次 揮手 :主機2向主機1發送 FIN 報文段,請求關閉連接,同時主機2進入 LAST_ACK 狀態;

  4. 第四次 揮手 :主機1收到主機2發送的 FIN 報文段,向主機2發送 ACK 報文段,然後主機1進入 TIME_WAIT 狀態;主機2收到主機1的 ACK 報文段以後,就關閉連接;此時,主機1等待2MSL後依然沒有收到回覆,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

三次握手可以簡單通俗理解爲:

1)A要跟B聊天,問B在嗎(收到了嗎)?(SYN)

2)B收到A,B回覆A說收到了,那我們開始吧。(ACK+SYN)

3)A收到B的回覆,A:那我們開始聊天(數據傳輸)。(ACK)

四次揮手可以簡答理解爲:

1)A跟B說,我要停止聊天了,你(B)還在嗎?準備中斷聊天了(FIN)

2)B收到A的消息,B回覆A說:我在。(ACK)

3)B再發一條消息給A說,A你可以停止了。(FIN)

4)A收到B說可以停止發消息了,A回覆B說:收到!(ACK)

1、TCP 爲什麼三次握手而不是兩次握手?

爲了實現可靠數據傳輸,TCP 協議的通信雙方,都必須維護一個序列號,以標識發送出去的數據包中,哪些是已經被對方收到的。三次握手的過程即是通信雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟。如果只是兩次握手,至多隻有連接發起方的起始序列號能被確認,另一方選擇的序列號則得不到確認。

2、爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?

答:因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。

3、爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可能最後一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。

文章關聯→→:

抓包神器:Wireshark 實例分析TCP三次握手過程

筆記系列↓↓↓:

筆記 | Java對象探祕

筆記 | JVM內存區域結構:一計兩棧一堆一區

筆記 | 併發編程的三大挑戰

筆記 | TCP與UDP的區別

筆記 | TCP如何保證可靠性

參考: http://www.jellythink.com/archives/705

相關文章