HTTP 是無連接的,所以作為下層的 TCP 協議也是無連接的,雖然看似 TCP 將兩端連接了起來,但是其實只是兩端共同維護了一個狀態。
建立連接三次握手
在 TCP 協議中,主動發起請求的一端為客戶端,被動連接的一端稱為服務端。不管是客戶端還是服務端,TCP 連接建立完后都能發送和接收數據,所以 TCP 也是一個全雙工的協議。
起初,兩端都為 CLOSED 狀態。在通信開始前,雙方都會創建 TCB。 服務器創建完 TCB 后遍進入 LISTEN 狀態,此時開始等待客戶端發送數據。
-
第一次握手
客戶端向服務端發送連接請求報文段。該報文段中包含自身的數據通訊初始序號。請求發送后,客戶端便進入 SYN-SENT 狀態,x 表示客戶端的數據通信初始序號。 -
第二次握手
服務端收到連接請求報文段后,如果同意連接,則會發送一個應答,該應答中也會包含自身的數據通訊初始序號,發送完成后便進入 SYN-RECEIVED 狀態。 -
第三次握手
當客戶端收到連接同意的應答后,還要向服務端發送一個確認報文。客戶端發完這個報文段后便進入ESTABLISHED 狀態,服務端收到這個應答后也進入 ESTABLISHED 狀態,此時連接建立成功。
第三次握手可以包含數據,通過 TCP 快速打開(TFO)技術。其實只要涉及到握手的協議,都可以使用類似 TFO 的方式,客戶端和服務端存儲相同 cookie,下次握手時發出 cookie 達到減少 RTT 的目的。
-
為何兩次握手即可建立鏈接,還需要第三次握手?
為了防止失效的連接請求報文段被服務端接收,從而產生錯誤。
斷開鏈接四次揮手
TCP 是全雙工的,在斷開連接時兩端都需要發送 FIN 和 ACK。
-
第一次揮手
若客戶端 A 認為數據發送完成,則它需要向服務端 B 發送連接釋放請求。 -
第二次揮手
B 收到連接釋放請求后,會告訴應用層要釋放 TCP 鏈接。然后會發送 ACK 包,并進入 CLOSE_WAIT 狀態,表示 A 到 B 的連接已經釋放,不接收 A 發的數據了。但是因為 TCP 連接時雙向的,所以 B 仍舊可以發送數據給 A。 -
第三次揮手
B 如果此時還有沒發完的數據會繼續發送,完畢后會向 A 發送連接釋放請求,然后 B 便進入 LAST-ACK 狀態。 -
第四次揮手
A 收到釋放請求后,向 B 發送確認應答,此時 A 進入 TIME-WAIT 狀態。該狀態會持續 2MSL(最大段生存期,指報文段在網絡中生存的時間,超時會被拋棄) 時間,若該時間段內沒有 B 的重發請求的話,就進入 CLOSED 狀態。當 B 收到確認應答后,也便進入 CLOSED 狀態。
第三次揮手通過延遲確認的技術(通常有時間限制,否則對方會誤認為需要重傳),可以將第二次和第三次揮手合并,延遲 ACK 包的發送。
-
為什么 A 要進入 TIME-WAIT 狀態,等待 2MSL 時間后才進入 CLOSED 狀態?
為了保證 B 能收到 A 的確認應答。若 A 發完確認應答后直接進入 CLOSED 狀態,如果確認應答因為網絡問題一直沒有到達,那么會造成 B 不能正常關閉。