關於 TCP 三次握手和四次揮手,滿分回答在此

2022-01-08 飛天小牛肉
0. 前言 

在面試中,計算機網絡的 TCP 三次握手和四次揮手是很常見的問題,但是在實際面試中,面試官會更願意聽到怎樣的回答呢?詳細程度是怎樣的?

越簡單常見的問題越不可小覷,萬丈高樓平地起,把簡單的問題深入化,才更能拉開與競爭者的距離。掌握了本文講的全部知識點,關於 TCP 三次握手和四次揮手基本就 OK 了 😊

1. TCP 和 UDP

講解 TCP 三次握手和四次握手之前,我們先了解一下 TCP 和 UDP 這兩個重量級的傳輸層協議。

💦 用戶數據報協議 UDP(User Datagram Protocol):

UDP 在傳送數據之前不需要先建立連接,遠程主機在收到 UDP 報文後,不需要給出任何確認。雖然 UDP 不提供可靠交付,但在某些情況下 UDP 確是一種最有效的工作方式(一般用於即時通信),比如:QQ 語音、 QQ 視頻 、直播等等

💦 傳輸控制協議 TCP(Transmission Control Protocol):

TCP 提供面向連接的服務。在傳送數據之前必須先建立連接,數據傳送結束後要釋放連接。TCP 不提供廣播或多播服務。由於 TCP 要提供可靠的,面向連接的傳輸服務(TCP的可靠體現在TCP在傳遞數據之前,會有三次握手來建立連接,而且在數據傳遞時,有確認、窗口、重傳、流量控制、擁塞控制機制,在數據傳完後,還會四次揮手斷開連接用來節約系統資源),這不僅使協議數據單元的首部增大很多,還要佔用許多處理機資源。TCP 一般用於文件傳輸、發送和接收郵件、遠程登錄等場景。2. TCP 報文段首部格式

TCP 報文段的具體格式大家可以不必都記住,但是其中的幾個控制位與我們接下來要講的三次握手和四次揮手息息相關,大家一定要牢記。

首部固定部分各欄位意義如下:

1 - 源埠和目的埠:各佔 2 個字節,分別寫入源埠和目的埠。IP 地址 + 埠號就可以確定一個進程地址

2 - 序號/序列號(Sequense Number,SN):在一個 TCP 連接中傳送的字節流中的每一個字節都按順序編號。該欄位表示本報文段所發送的數據的第一個字節的序號。初始序號稱為 Init Sequense Number, ISN(序號/序列號這個欄位很重要,大家留個印象,下文會詳細講解)

例如,一報文段的序號是 101,共有 100 字節的數據。這就表明:本報文段的數據的第一個字節的序號是 101,最後一個字節的序號是 200。顯然,下一個報文段的數據序號應當從 201 開始,即下一個報文段的序號欄位值應為 201。

3 - 確認號 ack:期望收到對方下一個報文段的第一個數據字節的序號。若確認號為 N,則表明:到序號 N-1 為止的所有數據都已正確收到。

4 - 數據偏移(首部長度):它指出 TCP 報文段的數據起始處距離 TCP 報文段的起始處有多遠。這個欄位實際上是指出TCP報文段的首部長度。

5 - 保留:佔 6 位,應置為 0,保留為今後使用。

⭐ 大家看上圖,保留位的右邊還有 6 個控制位(重要),這是TCP 用來說明該報文段性質的:

緊急位 URG:當 URG = 1 時,表明此報文段中有緊急數據,是高優先級的數據,應儘快發送,不用在緩存中排隊。該控制位需配合緊急指針使用(緊急指針指出本報文段中緊急數據的字節數)

舉個例子:我們需要取消一個已經發送了很長程序的運行,因此用戶從鍵盤發出中斷命令。如果不使用緊急數據,那麼這個指令將存儲在接收 TCP 的緩存末尾,只有在所有的數據被處理完畢後這兩個字符才被交付接收方的應用進程,這樣做就無法實現立即中斷。

確認 ACK:僅當 ACK = 1 時確認號欄位才有效,當 ACK = 0 時確認號無效。TCP 規定,在連接建立後所有傳送的報文段都必須把 ACK 置為 1。

推送 PSH:當兩個應用進程進行交互式的通信時,有時在一端的應用進程希望在鍵入一個命令後立即就能收到對方的響應。在這種情況下,TCP 就可以使用推送(push)操作。這時,發送方 TCP 把 PSH 置為 1,並立即創建一個報文段發送出去。接收方 TCP 收到 PSH = 1 的報文段,就儘快地交付接收應用進程。而不用等到整個緩存都填滿了後再向上交付。

復位 RST:當 RST = 1 時,表明 TCP 連接中出現了嚴重錯誤(如由於主機崩潰或其他原因),必須釋放連接,然後再重新建立傳輸連接。

同步 SYN:SYN = 1 表示這是一個連接請求或連接接受報文。

當 SYN = 1 而 ACK = 0 時,表明這是一個連接請求報文段。對方若同意建立連接,則應在響應的報文段中使 SYN = 1 且 ACK = 1。

終止 FIN:用來釋放一個連接。當 FIN = 1時,表明此報文段的發送發的數據已發送完畢,並要求釋放運輸連接。

3. TCP 三次握手建立連接① 三次握手過程詳解

三次握手的原文是 three-way handshake,整個名詞的可以翻譯為:需要三個步驟才能建立握手/連接的機制。當然,三次握手也可以叫 three-message handshake,通過三條消息來建立的握手/連接。

進行三次握手的主要作用就是為了確認雙方的接收能力和發送能力是否正常、指定自己的 初始化序列號(Init Sequense Number,  ISN) 為後面的可靠性傳輸做準備。

三次握手過程如下圖:

回顧一下圖中字符的含義:

ack:確認號。希望收到的下一個數據的第一個字節的序號

剛開始客戶端處於 Closed 的狀態,而服務端處於 Listen 狀態

CLOSED:沒有任何連接狀態

LISTEN:偵聽來自遠方 TCP 埠的連接請求

1)第一次握手:客戶端向服務端發送一個 SYN 報文(SYN = 1),並指明客戶端的初始化序列號 ISN(x),即圖中的 seq = x,表示本報文段所發送的數據的第一個字節的序號。此時客戶端處於 SYN_Send 狀態。

SYN-SENT :在發送連接請求後等待匹配的連接請求

2)第二次握手:伺服器收到客戶端的 SYN 報文之後,會發送 SYN 報文作為應答(SYN = 1),並且指定自己的初始化序列號 ISN(y),即圖中的 seq = y。同時會把客戶端的 ISN + 1 作為確認號 ack 的值,表示已經收到了客戶端發來的的 SYN 報文,希望收到的下一個數據的第一個字節的序號是 x + 1,此時伺服器處於 SYN_REVD 的狀態。

SYN-RECEIVED:在收到和發送一個連接請求後等待對連接請求的確認

3)第三次握手:客戶端收到伺服器端響應的 SYN 報文之後,會發送一個 ACK 報文,也是一樣把伺服器的 ISN + 1 作為 ack 的值,表示已經收到了服務端發來的的 SYN 報文,希望收到的下一個數據的第一個字節的序號是 y + 1,並指明此時客戶端的序列號 seq = x + 1(初始為 seq = x,所以第二個報文段要 +1),此時客戶端處於 Establised 狀態。

伺服器收到 ACK 報文之後,也處於 Establised 狀態,至此,雙方建立起了 TCP 連接。

ESTABLISHED:代表一個打開的連接,數據可以傳送給用戶

② 為什麼要三次握手

三次握手的目的是建立可靠的通信信道,說到通訊,簡單來說就是數據的發送與接收,而三次握手最主要的目的就是雙方確認自己與對方的發送與接收是正常的

只有經過三次握手才能確認雙發的收發功能都正常,缺一不可:

第一次握手(客戶端發送 SYN 報文給伺服器,伺服器接收該報文):客戶端什麼都不能確認;伺服器確認了對方發送正常,自己接收正常

第二次握手(伺服器響應 SYN 報文給客戶端,客戶端接收該報文):

客戶端確認了:自己發送、接收正常,對方發送、接收正常;

伺服器確認了:對方發送正常,自己接收正常

第三次握手(客戶端發送 ACK 報文給伺服器):

客戶端確認了:自己發送、接收正常,對方發送、接收正常;

伺服器確認了:自己發送、接收正常,對方發送、接收正常

③ ISN (Initial Sequence Number) 是固定的嗎

三次握手的其中一個重要功能是客戶端和服務端交換 ISN(Initial Sequence Number),以便讓對方知道接下來接收數據的時候如何按序列號組裝數據

當一端為建立連接而發送它的 SYN 時,它會為連接選擇一個初始序號。ISN 隨時間而變化,因此每個連接都將具有不同的 ISN。如果 ISN 是固定的,攻擊者很容易猜出後續的確認號,因此 ISN 是動態生成的

④ 三次握手過程中可以攜帶數據嗎

第三次握手的時候,是可以攜帶數據的。但是,第一次、第二次握手絕對不可以攜帶數據

假如第一次握手可以攜帶數據的話,如果有人要惡意攻擊伺服器,那他每次都在第一次握手中的 SYN 報文中放入大量的數據,然後瘋狂重複發 SYN 報文的話(因為攻擊者根本就不用管伺服器的接收、發送能力是否正常,它就是要攻擊你),這會讓伺服器花費很多時間、內存空間來接收這些報文。

⭐ 簡單的記憶就是,請求連接/接收 即 SYN = 1 的時候不能攜帶數據

而對於第三次的話,此時客戶端已經處於 ESTABLISHED 狀態。對於客戶端來說,他已經建立起連接了,並且也已經知道伺服器的接收、發送能力是正常的了,所以當然能正常發送/攜帶數據了。

⑤ 半連接隊列

伺服器第一次收到客戶端的 SYN 之後,就會處於 SYN_RCVD 狀態,此時雙方還沒有完全建立其連接,伺服器會把這種狀態下的請求連接放在一個隊列裡,我們把這種隊列稱之為半連接隊列

當然還有一個全連接隊列,完成三次握手後建立起的連接就會放在全連接隊列中。如果隊列滿了就有可能會出現丟包現象。

⑥ SYN 洪泛攻擊

SYN 攻擊就是 Client 在短時間內偽造大量不存在的 IP 地址,並向 Server 不斷地發送 SYN 包,Server 則回復確認包,並等待 Client 確認,由於源地址不存在,因此 Server 需要不斷重發直至超時,這些偽造的 SYN 包將長時間佔用半連接隊列,導致正常的 SYN 請求因為隊列滿而被丟棄,從而引起網絡擁塞甚至系統癱瘓。

⑦ 如果第三次握手丟失了,客戶端服務端會如何處理

伺服器發送完 SYN-ACK 包,如果未收到客戶端響應的確認包,也即第三次握手丟失。那麼伺服器就會進行首次重傳,若等待一段時間仍未收到客戶確認包,就進行第二次重傳。如果重傳次數超過系統規定的最大重傳次數,則系統將該連接信息從半連接隊列中刪除。

注意,每次重傳等待的時間不一定相同,一般會是指數增長,例如間隔時間為 1s,2s,4s,8s…

4. TCP 四次揮手釋放連接① 四次揮手過程詳解

建立一個 TCP 連接需要三次握手,而終止一個 TCP 連接要經過四次揮手(也有將四次揮手叫做四次握手的)。這是由於 TCP 的半關閉(half-close)特性造成的,TCP 提供了連接的一端在結束它的發送後還能接收來自另一端數據的能力。

TCP 連接的釋放需要發送四個包(執行四個步驟),因此稱為四次揮手(Four-way handshake),客戶端或服務端均可主動發起揮手動作

回顧一下上圖中符號的意思:

ack:確認號。希望收到的下一個數據的第一個字節的序號

剛開始雙方都處於ESTABLISHED 狀態,假設是客戶端先發起關閉請求。四次揮手的過程如下:

1)第一次揮手:客戶端發送一個 FIN 報文(請求連接終止:FIN = 1),報文中會指定一個序列號 seq = u。並停止再發送數據,主動關閉 TCP 連接。此時客戶端處於 FIN_WAIT1 狀態,等待服務端的確認。

FIN-WAIT-1 - 等待遠程TCP的連接中斷請求,或先前的連接中斷請求的確認;

2)第二次揮手:服務端收到 FIN 之後,會發送 ACK 報文,且把客戶端的序號值 +1 作為 ACK 報文的序列號值,表明已經收到客戶端的報文了,此時服務端處於 CLOSE_WAIT 狀態。

CLOSE-WAIT - 等待從本地用戶發來的連接中斷請求;

此時的 TCP 處於半關閉狀態,客戶端到服務端的連接釋放。客戶端收到服務端的確認後,進入FIN_WAIT2(終止等待 2)狀態,等待服務端發出的連接釋放報文段。

FIN-WAIT-2 - 從遠程TCP等待連接中斷請求;

3)第三次揮手:如果服務端也想斷開連接了(沒有要向客戶端發出的數據),和客戶端的第一次揮手一樣,發送 FIN 報文,且指定一個序列號。此時服務端處於 LAST_ACK 的狀態,等待客戶端的確認。

LAST-ACK - 等待原來發向遠程TCP的連接中斷請求的確認;

4)第四次揮手:客戶端收到 FIN 之後,一樣發送一個 ACK 報文作為應答(ack = w+1),且把服務端的序列值 +1 作為自己 ACK 報文的序號值(seq=u+1),此時客戶端處於 TIME_WAIT (時間等待)狀態

TIME-WAIT - 等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認;

🚨 注意 !!!這個時候由服務端到客戶端的 TCP 連接並未釋放掉,需要經過時間等待計時器設置的時間 2MSL(一個報文的來回時間) 後才會進入 CLOSED 狀態(這樣做的目的是確保服務端收到自己的 ACK 報文。如果服務端在規定時間內沒有收到客戶端發來的 ACK 報文的話,服務端會重新發送 FIN 報文給客戶端,客戶端再次收到 FIN 報文之後,就知道之前的 ACK 報文丟失了,然後再次發送 ACK 報文給服務端)。服務端收到 ACK 報文之後,就關閉連接了,處於 CLOSED 狀態。

② 為什麼要四次揮手

由於 TCP 的半關閉(half-close)特性,TCP 提供了連接的一端在結束它的發送後還能接收來自另一端數據的能力。

任何一方都可以在數據傳送結束後發出連接釋放的通知,待對方確認後進入半關閉狀態。當另一方也沒有數據再發送的時候,則發出連接釋放通知,對方確認後就完全關閉了TCP連接。

通俗的來說,兩次握手就可以釋放一端到另一端的 TCP 連接,完全釋放連接一共需要四次握手

舉個例子:A 和 B 打電話,通話即將結束後,A 說 「我沒啥要說的了」,B 回答 「我知道了」,於是 A 向 B 的連接釋放了。但是 B 可能還會有要說的話,於是 B 可能又巴拉巴拉說了一通,最後 B 說「我說完了」,A 回答「知道了」,於是 B 向 A 的連接釋放了,這樣整個通話就結束了。

相關焦點

  • 關於TCP三次握手和四次揮手,滿分回答在此
    前 言在面試中,計算機網絡的 TCP 三次握手和四次揮手是很常見的問題,但是在實際面試中,面試官會更願意聽到怎樣的回答呢?詳細程度是怎樣的?越簡單常見的問題越不可小覷,萬丈高樓平地起,把簡單的問題深入化,才更能拉開與競爭者的距離。
  • TCP三次握手及四次揮手詳細圖解
    TCP三次握手所謂三次握手(Three-way Handshake),是指建立一個TCP連接時,需要客戶端和伺服器總共發送3個包。三次握手的目的是連接伺服器指定埠,建立TCP連接,並同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息.在socket編程中,客戶端執行connect()時。將觸發三次握手。
  • TCP三次握手,四次揮手,你真的懂嗎?
    本文來自於作者投稿,公眾號:碼農桃花源這時候我會「胸有成竹」地「背誦」前期準備好的「答案」,第一次怎麼怎麼,第二次……答完後就沒有下文了,面試官貌似也沒有深入下去的意思,深入下去我也不懂,皆大歡喜!作為程式設計師,要有「刨根問底」的精神,知其然,更要知其所以然。這篇文章希望能抽絲剝繭,還原背後的原理。
  • 理解TCP/IP三次握手與四次揮手的正確姿勢
    這個故事可以解釋TCP為什麼要三次握手嗎 ... 囧關於四次揮手先由客戶端向伺服器端發送一個FIN,請求關閉數據傳輸。,四次揮手估計就..所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。
  • 35 張圖解被問千百遍的 TCP 三次握手和四次揮手面試題
    所以小林整理了關於 TCP 三次握手和四次揮手的面試題型,跟大家一起探討探討。TCP 基本認識1.TCP 連接建立2.TCP 連接斷開3.Socket 編程PS:本次文章不涉及 TCP 流量控制、擁塞控制、可靠性傳輸等方面知識,這些留在下篇哈!
  • 以女朋友為例講解 TCP/IP 三次握手與四次揮手
    註:以下情節純屬虛構方案TCP建立連接為什麼是三次握手,而不是兩次或四次?TCP,名為傳輸控制協議,是一種可靠的傳輸層協議,IP協議號為6。順便說一句,原則上任何數據傳輸都無法確保絕對可靠,三次握手只是確保可靠的基本需要。舉個日常例子,打電話時我們對話如下:
  • 一文徹底搞懂 TCP三次握手、四次揮手過程及原理
    這個故事可以解釋TCP為什麼要三次握手嗎 ... 囧關於四次揮手先由客戶端向伺服器端發送一個FIN,請求關閉數據傳輸。當伺服器接收到客戶端的FIN時,向客戶端發送一個ACK,其中ack的值等於FIN+SEQ然後伺服器向客戶端發送一個FIN,告訴客戶端應用程式關閉。
  • TCP的 「三次握手」 和「四次揮手」,到底是什麼鬼?
    請看圖,記住有三個箭頭,四個對話框,就可以記住口訣:三次握手與四次揮手:TCP的三次握手,那麼你了解什麼是TCP了嗎?我相信有的人還記得,但是總會有人又忘記了,了解TCP頭部報文,還有為什麼是TCP的三次握手,而不是其他次數呢?在TCP三次握手過程中,有什麼區別或者是說變化。TCP,請記住中文名,傳輸控制協議,是一種面向連接的,可靠的,基於字節流的傳輸層通信協議,TCP的頭部報文,你了解嗎?不了解即可百度。
  • 拜託,不要再問我三次握手和四次揮手了!
    很多小夥伴說這個問題剛開始回答的挺好,但是後面越回答越冒冷汗,最後就歇菜了。見過比較典型的面試場景是這樣的:面試官:請介紹下三次握手求職者:第一次握手就是客戶端給伺服器端發送一個報文,第二次就是伺服器收到報文之後,會應答一個報文給客戶端,第三次握手就是客戶端收到報文後再給伺服器發送一個報文,三次握手就成功了。面試官:然後呢?求職者:這就是三次握手的過程,很簡單的。
  • 重學TCP/IP協議和三次握手四次揮手
    劃重點:TCP(傳輸控制協議)和IP(網際協議) 是最先定義的兩個核心協議,所以才統稱為TCP/IP協議族TCP的三次握手四次揮手TCP是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,在發送數據前,通信雙方必須在彼此間建立一條連接。
  • TCP/IP三次握手與四次揮手學習筆記(一)
    劃重點:TCP(傳輸控制協議)和IP(網際協議) 是最先定義的兩個核心協議,所以才統稱為TCP/IP協議族TCP的三次握手四次揮手TCP是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,在發送數據前,通信雙方必須在彼此間建立一條連接。
  • 面試官,不要再問我三次握手和四次揮手
    三次握手和四次揮手是各個公司常見的考點,也具有一定的水平區分度,也被一些面試官作為熱身題。很多小夥伴說這個問題剛開始回答的挺好,但是後面越回答越冒冷汗,最後就歇菜了。見過比較典型的面試場景是這樣的:面試官:請介紹下三次握手求職者:第一次握手就是客戶端給伺服器端發送一個報文,第二次就是伺服器收到報文之後,會應答一個報文給客戶端,第三次握手就是客戶端收到報文後再給伺服器發送一個報文,三次握手就成功了。面試官:然後呢?求職者:這就是三次握手的過程,很簡單的。
  • 傳輸層協議 TCP:TCP 為什麼握手是 3 次、揮手是 4 次?
    TCP 的握手和揮手TCP 是一個連接導向的協議,設計有建立連接(握手)和斷開連接(揮手)的過程。TCP 沒有設計會話(Session),因為會話通常是一個應用的行為。建立連接的過程(三次握手)因為要保持連接和可靠性約束,TCP 協議要保證每一條發出的數據必須給返回,返回數據叫作 ACK(也就是響應)。按照這個思路,你可以看看建立連接是不是需要 3 次握手:
  • TCP 三次握手、四手揮手,這樣說你能明白吧!
    1,序列號為,期望下一次收到的數據包的序列號為 A機器和B機器連接建立成功 TCP三次握手抓包驗證 以為驗證三次握手是否描述正確,在下使用進行抓包驗證。
  • 牛皮了,頭一次見有大佬把TCP三次握手四次揮手解釋的這麼明白
    劃重點:TCP(傳輸控制協議)和IP(網際協議) 是最先定義的兩個核心協議,所以才統稱為TCP/IP協議族TCP的三次握手四次揮手TCP是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,在發送數據前,通信雙方必須在彼此間建立一條連接。所謂的「連接」,其實是客戶端和服務端保存的一份關於對方的信息,如ip地址、埠號等。
  • 牛皮了,頭一次見有大佬把TCP三次握手四次揮手解釋的這麼明白
    劃重點:TCP(傳輸控制協議)和IP(網際協議) 是最先定義的兩個核心協議,所以才統稱為TCP/IP協議族TCP的三次握手四次揮手TCP是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,在發送數據前,通信雙方必須在彼此間建立一條連接
  • 從源碼看tcp三次握手(上)
    著名的TCP三次握手 前面已經介紹過常用套接字接口函數,也就是伺服器調用bind、listen 以及 accept 等待客戶端進行連接,而客戶端connect函數主動請求連接伺服器。當客戶端使用tcp套接字進行連接時,調用 connect 函數將激發 TCP 的三次握手過程。如下圖:TCP三次握手的剖析 這裡我們使用的網絡編程模型都是阻塞式的。所謂阻塞式,就是調用發起後不會直接返回,由作業系統內核處理之後才會返回。相對的,還有一種叫做非阻塞式的,暫時先不討論。
  • TCP 三次握手原理,你真的理解嗎?
    問題描述場景:JAVA的client和server,使用socket通信。server使用NIO。1.間歇性得出現client向server建立連接三次握手已經完成,但server的selector沒有響應到這連接。2.出問題的時間點,會同時有很多連接出現這個問題。
  • Wireshark 基本介紹和學習 TCP 三次握手
    記得大學的時候就學習過TCP的三次握手協議,那時候只是知道,雖然在書上看過很多TCP和UDP的資料,但是從來沒有真正見過這些數據包, 老是感覺在雲上飄一樣,學得不踏實。有了wireshark就能截獲這些網絡數據包,可以清晰的看到數據包中的每一個欄位。更能加深我們對網絡協議的理解。對我而言, wireshark 是學習網絡協議最好的工具。
  • 如果TCP不握手三次,改成兩次或者四次會怎樣?
    其實呢,三次握手就是為了對每次發送的數據量進行跟蹤與協商,確保數據段的發送和接收同步,根據所接收到的數據量而確認數據發送、接收完畢後何時撤消聯繫,並建立虛連接。那說了半天,到底握手是怎麼握?TCP 為什麼是三次握手而不是兩次或四次?