所謂『揮手』,即終止 TCP 連接,就是指斷開一個 TCP 連接時,需要客戶端和服務端總共發出四個包,已確認連接的斷開。
在 Socket 編程中,這一過程由客戶端或服務端任意一方執行 Close來觸發。
這裡假設,由客戶端主動觸發 Close:
數據傳輸完畢之後,雙方都可釋放連結,最開始,客戶端和服務端都處於 Established 的狀態,然後客戶端主動關閉,服務端被動關閉。
第一次揮手:首先,客戶端進程發出連接釋放報文,並且停止發送數據,在該數據包的報頭中,TCP Flags 中的 FIN 就為1,假設,此時的客戶端定義的序列號 seq=u,該值等於前面 Established 狀態下數據最後一次傳送到服務端的數據的最後字節的序號+1,此時客戶端就進入了 FIN_WAIT_1 這麼一個終止等待的狀態。TCP 規定,即使 FIN 報文段不攜帶數據,也要消耗掉一個序號。
第二次揮手:伺服器收到 FIN 包後,也要發出 ACK 確認報文,這裡最為回應,小寫的 ack=u+1,同樣也攜帶上了自己的序列號。此時服務端進入了 CLOSE_WAIT 這麼一個關閉等待的狀態。這個狀態比較重要,TCP 伺服器通知高層的應用進程,客戶端要釋放跟伺服器通信的連接了,這時候會處於半關閉的狀態,即客戶端已經沒有數據要發送了,但是服務端又要發送數據,客戶端還是能夠接收的。這個狀態還要持續一段時間。客戶端收到伺服器的確認請求後,也就是第二次揮手的時候。此時,客戶端就進入了 FIN_WAIT_2 這個狀態,等待伺服器發送釋放連接報文,等待發送第三次揮手的請求。因此在這段時間內,客戶端有可能還要接受伺服器發送的最後的數據。
第三次揮手:伺服器將最後的數據發送完畢,就會想客戶端發送連接釋放報文,這裡 FIN=1,ACK=1。而 ack 還是等於 u+1。由於在半關閉的狀態,伺服器有可能還發送了一些數據,假定此時的序號就變為了 w。此時,伺服器就進入了 LAST_ACK 這麼一個最後確認的狀態,等待客戶端的最終確認。
第四次揮手:客戶端在收到伺服器的連接釋放報文之後,必須發出確認,即:ACK=1,再將伺服器發過來的w變成w+1,回發回去,通過小的ack回發回去,而自己的序號假定為那麼它就是u+1,而自己的序號,也就是按照之前報文的序號加1,就是u+1。此時,客戶端就進入了 TIME_WAIT 即時間等待的狀態。注意此時,客戶端的 TCP 連接還沒有釋放,必須經過 2 * MSL 的時間後,這個連接才真正的釋放,才進入到 CLOSED 的狀態。MSL 即最長報文段壽命,RFC 793 定義了 MSL 的值為2分鐘,而 Linux 則設置成了30秒。而伺服器,只要收到了客戶端的確認,立即就進入了 CLOSED 的狀態。伺服器結束TCP的連結時間要比客戶端稍早一些。
輕輕的我走了,我揮一揮衣袖,不帶走半片雲彩!
四次揮手總結玩了,下一期會總結三次握手和四次揮手的面試重點。
關注我,我將持續更新。有什麼問題也可以留言。
感謝您的觀看