TCP 三次握手 & 四次揮手

TCP 位於傳輸層,提供可靠的字節流服務。php

可靠的字節流服務:TCP 協議爲了傳輸方便,將大塊數據分割成以 報文段(segment)爲單位的數據包進行管理,並可以把這些數據準確可靠的傳遞給對方。

TCP報文段格式

下面是一張 TCP 報文格式的圖片:html

TCP報文段格式

其中,幾個比較重要的字段以下:緩存

序號和確認號

每一個 TCP 報文內都有序號和確認號,結合重傳機制保障數據傳輸的可靠性服務器

  • seq 序號:TCP 鏈接字節流中每個字節都會有一個編號,當創建鏈接的時候,TCP 選定一個初始序號(隨機數),以後每發送一個數據包(消息),就將

序號+1,保證每發送不一樣的數據包,數據包的序號都是不一樣的網絡

  • ack 確認號:表示但願收到的下一個報文段部分的第一個字節的序號是 seq+1,之前的字節已經收到過了,ACK標誌位被設置爲1的時候,纔會發送ack確認號。

6個標誌位

TCP 報文共有6個標誌位,每一個佔1位,共6位,每一位的值只有0和1spa

  • SYN:同步標誌位,SYN=1 時,表示這是一個鏈接請求報文
  • ACK:確認標誌位,ACK=1 時,表示確認號有效,當 TCP 發送 ACK 時,至關於返回結果,須要帶有確認序號,以便跟發送的消息對應起來。
  • FIN:終止標誌位,FIN=1 時,表示此報文段的發送方數據已發送完畢,要求釋放 TCP 鏈接
  • PSH:推送標誌位,PSH=1 時表示該段報文高優先級,接收方應儘快推送給應用程序,而不用等整個 TCP 緩存都填滿了在交付
  • URG:緊急標誌位,URG=1 時表示緊急指針有效,此報文中有緊急數據要儘快傳送,不須要按照原來的排列順序來傳送
  • RST:復位標誌位,RST=1 時表示 TCP 鏈接中出現錯誤,須要釋放並從新創建鏈接

創建 TCP 鏈接:三次握手

TCP 鏈接的創建採用客戶-服務器模式,主動發起鏈接創建的應用進程叫作客戶,被動等待鏈接創建的應用進程叫作服務器,如下是創建 TCP 鏈接的過程:.net

TCP三次握手

第一次握手

客戶端向服務端發送請求鏈接報文,將報文同步標誌位 SYN 的值設置爲1,表示要建立鏈接,等待服務器確認,並進入SYN_SENT狀態。(報文首部:SYN=1, 初始序號 seq=x(x爲隨機生成數值))3d

第二次握手

服務端接收到客戶端的請求,回覆給客戶端確認報文,將報文確認標誌位 ACK 的值設置爲1,告訴客戶端已收到它的請求,贊成建立鏈接,並進入SYN_RECV狀態。(ACK=1,確認號 ack=x+1,SYN=1,初始序號 seq=y)指針

第三次握手

客戶端接收到服務端的確認報文以後,爲了防止意外,再次向服務端發出確認報文,將報文ACK 的值設置爲1,當服務端收到客戶端發來的確認報文以後,TCP 鏈接創建,客戶端和服務端都進入ESTABLISHED狀態,完成三次握手,之後就能夠開森的傳遞數據了。(報文首部:ACK=1, 確認號 ack=y+1, 序號 seq=x+1(服務端傳過來的ack的值)code

斷開 TCP 鏈接:四次揮手

因爲 TCP 鏈接是雙工的,所以每一個方向都必須單獨進行關閉。當一方完成它的數據發送任務後就能夠發送一個FIN終止標誌位來終止這個方向上的鏈接,收到一個FIN就意味着這一方向上沒有數據流動。一個 TCP 鏈接在收到一個 FIN 後仍能發送數據,首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉

TCP四次揮手

第一次揮手

客戶端主動向服務端發出斷開 TCP 鏈接的請求報文,將報文終止標誌位 FIN 設置爲1,表示要釋放 TCP 鏈接,並進入等待結束鏈接狀態FIN_WAIT-1(報文首部:FIN=1,序號 seq=u(u爲隨機數))

第二次揮手

服務端收到客戶端的釋放鏈接請求後,回覆確認報文給客戶端,將報文確認標誌位 ACK 設置爲1,表示已收到客戶端請求,關閉服務端讀通道並進入關閉等待狀態 CLOSE-WAIT(報文首部:ACK=1,確認號 ack=u+1(收到的序號+1),序號 seq=v(v爲隨機數))

客戶端收到確認報文後,會關閉客戶端寫通道,此時客戶端仍能經過讀通道讀取服務端的數據,服務器仍能經過寫通道寫數據。

第三次揮手

服務端發送斷開 TCP 鏈接的請求報文,將報文終止標誌位 FIN 設置爲1。表示服務端數據已發送完畢,要釋放鏈接,不會再發送任何數據了。(報文首部:FIN=1,ACK=1,確認號 ack=u+1(收到的序號+1),序號 seq=w(w爲隨機數))

第四次揮手

客戶端收到服務端的斷開鏈接請求後,回覆確認報文,將報文確認標誌位 ACK 設置爲1關閉客戶端讀通道,服務端收到客戶端的確認報文後,關閉服務端讀通道。雙方讀寫通道所有關閉,完成四次揮手。(報文首部:ACK=1,確認號 ack=w+1(收到的序號+1),序號 seq=u+1(服務端傳過來的ack的值))

狀態概述

  • LISTEN:偵聽來自遠方TCP端口的鏈接請求
  • SYN-SENT:在發送鏈接請求後等待匹配的鏈接請求
  • SYN-RECEIVED:在收到和發送一個鏈接請求後等待對鏈接請求的確認
  • ESTABLISHED:表明一個打開的鏈接,數據能夠傳送給用戶
  • FIN-WAIT-1:等待遠程TCP的鏈接中斷請求,或先前的鏈接中斷請求的確認
  • FIN-WAIT-2:從遠程TCP等待鏈接中斷請求
  • CLOSE-WAIT:等待從本地用戶發來的鏈接中斷請求
  • CLOSING:等待遠程TCP對鏈接中斷的確認
  • LAST-ACK:等待原來發向遠程TCP的鏈接中斷請求的確認
  • TIME-WAIT:等待足夠的時間以確保遠程TCP接收到鏈接中斷請求的確認
  • CLOSED:沒有任何鏈接狀態

幾個疑問

爲何要三次握手而不是兩次握手?

爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。

2MSL

在結束鏈接的過程當中,爲何在收到服務器端的鏈接釋放報文段以後,客戶端還要繼續等待2MSL以後才真正關閉TCP鏈接呢?

這裏有兩個緣由:

第一個是:須要保證服務器端收到了客戶端的最後一條確認報文。假如這條報文丟失,服務器沒有接收到確認報文,就會對鏈接釋放報文進行超時重傳,而此時客戶端鏈接已關閉,沒法作出響應,就形成了服務器端不停重傳鏈接釋放報文,而沒法正常進入關閉狀態的情況。而等待2MSL,就能夠保證服務器端收到了最終確認;若服務器端沒有收到,那麼在2MSL以內客戶端必定會收到服務器端的重傳報文,此時客戶端就會重傳確認報文,並重置計時器。

第二個是:存在一種「已失效的鏈接請求報文段」,須要避免這種報文端出如今本鏈接中,形成異常。這種「已失效的鏈接請求報文段」是這麼造成的:假如客戶端發出了鏈接請求報文,然而服務器端沒有收到,因而客戶端進行超時重傳,再一次發送了鏈接請求報文,併成功創建鏈接。然而,第一次發送的鏈接請求報文並無丟失,只是在某個網絡結點中發生了長時間滯留,隨後,這個最初發送的報文段到達服務器端,會使得服務器端誤覺得客戶端發出了新的請求,形成異常。

資料

🍃 資料1:史上最容易理解的:TCP三次握手,四次揮手

🍃 資料2:TCP三次握手原理

🍃 資料3:TCP的三次握手(創建鏈接)和四次揮手(關閉鏈接)

相關文章
相關標籤/搜索