1. 前言
上一章節分析了 TCP 建立連接的過程,既然有建立連接,對應的也有斷開連接。數據傳輸完成之后,客戶端和服務器端保持通信狀態會占用資源開銷,所以需要斷開連接,TCP 協議中斷開連接也被稱為 TCP 四次揮手。
2.1 TCP 四次揮手
面試官提問: 說明一下 TCP 斷開連接的過程,涉及到了幾個步驟?
題目解析:
?
首先從行為上分析,TCP 斷開連接總共需要發送四次報文,也就是 "四次揮手" 的過程。
我們定義發送報文的一方是客戶端,接收報文的一方是服務器端。
上一章節中已經對三次握手過程做出了分析,在建立連接后到傳輸數據的整個過程,客戶端和服務器端均處于 ESTABLISHED(監聽)狀態,之后四次揮手的過程如下:
(1)第一次揮手:客戶端發送一個請求結束報文,其中 FIN 標志位設置為 1,報文中給定一個序列號 u,報文內容是 FINbit=1 seq=u
,發送之后主動進入 FIN_WAIT 狀態,等待服務器端的確認報文;
(2)第二次揮手:服務器端收到 FIN 報文,會發送 ACK 確認報文,并且把客戶端發送的序列號加一作為確認報文的確認號,表示已經收到了客戶端的報文,所以報文內容是 ACKbit=1 seq=v ack=u+1
,之后進入 CLOSE_WAIT(關閉等待)狀態。此時會通知應用層的進程,客戶端已經不會再發送數據了。此時連接處于半關閉狀態,如果服務器端發送數據,客戶端還是需要接收。
客戶端收到第二次揮手的報文后,會進入 FIN_WAIT_2(等待結束)狀態,等待服務器發送最后的終止連接報文;
(3)第三次揮手:服務器端把最后的數據發送之后,就開始向客戶端發送請求結束報文,FIN 標志位設置為 1,確認號設置為 u+1,比較特殊的一點是報文中 ACK 標志位也是 1,報文內容是 FINbit=1 ACKbit=1 seq=w ack=u+1
,發送之后服務器端進入 LAST_ACK(最終確認)狀態,等待客戶端的確認報文。
(4)第四次揮手:客戶端收到服務器的請求斷開連接報文后,必須還要發出一個確認報文,ACK 標志位設置為 1,并且序列號同上一報文的確認號,確認號同上一報文的序列號加一,報文內容是 ACKbit=1 seq=u+1 ack=w+1
,之后客戶端進入 TIME_WAIT(時間等待)狀態。因為不會再收到服務器端的報文,所以等待 2*MSL(最大報文段生存時間)之后,自動進入 CLOSED(關閉)狀態。
服務器端在收到客戶端的第四次揮手報文后,立即進入 CLOSED(關閉)狀態,表示結束本次 TCP 連接。
在向面試官分析整個流程的時候,我們可以將四次報文中的第一次和第二次看作一個整體,即是客戶端發送請求結束報文以及收到對應響應。第三次和第四次又是一個整體,即服務器端發送請求結束報文并且收到客戶端的響應。
2.2 為什么建立連接是三次握手,斷開連接需要四次揮手
面試官提問: 為什么 TCP 建立連接只需要三次握手,而 TCP 斷開連接需要四次握手?
題目解析:
關于 TCP 建立連接三次握手的必要性,我們已經在上一章節進行了分析,這里不再贅述,這里分析下四次握手的必要性。
前置說明:TCP 是雙向通信的協議,客戶端可以發送和接收數據,服務器端也可以發送和接收數據,也就是全雙工通信模式。
第一次揮手時,服務器端收到了客戶端的 FIN 請求結束報文,但是因為應用層的進程可能還需要傳輸一些數據,不能立即關閉 SOCKET,所以只能先給客戶端發送一個 ACK 確認報文,讓客戶端有 "心理準備"。之后服務器端進入 CLOSE_WAIT 狀態,這個狀態是為了處理最后的一些數據,等待這些數據也傳輸完畢之后,服務器端再發送 FIN 請求結束報文,到這里就已經有三次揮手的步驟了。最后,因為服務器端也需要感知第三次揮手的報文是否成功傳輸到客戶端,所以客戶端還需要第四次揮手的報文,來作為確認。
2.3 TIME_WAIT 狀態
面試官提問: 第四次揮手之后,客戶端進入的 TIME_WAIT 狀態是什么含義?有什么限制?
題目解析:
在候選人成功向面試官闡述了四次揮手的過程細節以及四次的必要性之后,面試官大概率會針對 TIME_WAIT 這個狀態發出提問。
我們將這個問題拆解開來,分步分析:
(1)TIME_WAIT 狀態的開始時間:TCP 連接中主動關閉連接的一方(一般看作客戶端)發送完最后一次揮手,主動關閉方就進入 TIME_WAIT 狀態。
(2)TIME_WAIT 的持續時間:TIME_WAIT 的時間是 2*MSL(Maximum Segment Lifetime),即兩個最大數據段生命周期。
(3)TIME_WAIT 為什么要持續 2*MSL 這么長的時間:
① 防止丟失報文導致異常:客戶端發送的最后一個 ACK 報文可能丟失,服務器端收不到響應則會發送第三次揮手的超時重傳報文,我們假設客戶端沒有 TIME_WAIT 狀態,而是直接進入 CLOSED 狀態,則會收到非法的報文段,返回一個 RST(拒絕連接)的報文,產生異常。
② 防止報文在網絡中停止影響下次建立連接:MSL 表示報文在網絡中的最大傳輸時間,等待 2*MSL 可以讓網絡中的所有舊報文段都失效,下一次重新三次握手時就不會收到無效的報文段。
3. 小結
本章節給大家分析了 TCP 關閉連接的過程以及常見提問,需要大家能夠在白紙上畫出 TCP 四次揮手的每個流程,并且重點關注 TIME_WAIT 這個狀態。