引言

在TCP/IP協議棧中,TCP(傳輸控制協議)就像“網絡世界的可靠信使”——它不像UDP那樣“丟三落四”,而是通過嚴謹的“握手建連”和“揮手斷連”,確保數據能從發送端完整、有序地抵達接收端。本文將結合文檔內容,用“生活場景類比”拆解三次握手四次揮手的細節,同時梳理關鍵技術點,幫你徹底搞懂這兩個TCP核心機制。

一、先搞懂前提:TCP為什麼需要“握手”和“揮手”?

TCP-三次握手和四次揮手簡單理解_#網絡

TCP的核心特性是面向連接、可靠傳輸。就像現實中“寄重要快遞”:

  • 寄件前,你得先確認收件人“在家且能收件”(對應“握手建連”,確認雙方收發能力);
  • 寄完後,你得告知收件人“所有包裹已寄完,不用等了”(對應“揮手斷連”,確認雙方無數據可傳)。

如果沒有這兩步:要麼“快遞寄了沒人收”(數據丟失),要麼“收件人一直等包裹”(資源浪費)。文檔中也明確提到,TCP的連接管理是其可靠性的關鍵組成部分,而三次握手與四次揮手正是連接管理的核心流程🔶1-129🔶。

二、TCP三次握手:如何“建立可靠連接”?

三次握手的本質是**“雙向確認”** ——不僅要確認“我能發給你”,還要確認“你能發給我,且我能收到你的回覆”。我們用“兩個人打電話”的場景類比,同時結合文檔中的狀態變化和數據交互細節拆解。

1. 參與角色與初始狀態

  • 客户端:主動發起連接的一方(比如你用瀏覽器訪問服務器)。初始狀態為CLOSED,通過socket()創建通信文件描述符後,調用connect()函數向服務器發起連接請求,進入SYN_SENT狀態。
  • 服務器:被動接收連接的一方(比如阿里雲上的Web服務器)。初始狀態為CLOSED,通過socket()創建listenfd(監聽描述符),再經bind()綁定IP和端口、listen()開啓監聽後,進入LISTEN狀態,等待客户端的連接請求。

2. 三次握手詳細步驟:像“打電話接通”的過程

TCP-三次握手和四次揮手簡單理解_#tcp/ip_02

步驟

類比場景(你→朋友)

技術層面(客户端→服務器)

核心數據與標誌位

雙方狀態變化

第一次握手(“喂,你在嗎?”)

你撥打朋友電話,等待對方接聽

客户端發送SYN報文段(同步報文),表示“我想和你建立連接”

- 客户端初始序列號(Seq = x,比如x=100)

- 標誌位SYN=1(SYN=Synchronize,同步請求)

客户端:CLOSEDSYN_SENT(等待服務器回覆)

服務器:LISTENSYN_RCVD(收到請求,準備回覆)

第二次握手(“我在!你能聽到嗎?”)

朋友接起電話,回覆“我在”,同時確認“能聽到你的聲音”

服務器收到SYN後,回覆SYN+ACK報文段,既同步自己的信息,又確認客户端的請求

- 服務器初始序列號(Seq = y,比如y=200)

- 確認號(Ack = x+1 = 101,表示“已收到你Seq=100的報文”)

- 標誌位SYN=1(服務器同步)+ ACK=1(ACK=Acknowledgment,確認有效)

服務器:SYN_RCVD(等待客户端最終確認)

客户端:收到後驗證Ack=101(正確),進入ESTABLISHED(連接初步建立,可準備發數據)

第三次握手(“能聽到!那我們開始説吧”)

你回覆“能聽到”,確認雙方溝通通道已通

客户端收到SYN+ACK後,發送ACK報文段,最終確認連接

- 確認號(Ack = y+1 = 201,表示“已收到你Seq=200的報文”)

- 標誌位ACK=1(最終確認)

客户端:ESTABLISHED(連接完全建立,可發數據)

服務器:收到Ack=201(正確),進入ESTABLISHED(連接完全建立,可收/發數據)

3. 為什麼是“三次”而不是“兩次”?

很多人會問:第二次握手時服務器已經回覆了SYN+ACK,為什麼客户端還要再發一次ACK?
舉個反例:如果只有兩次握手,假設客户端早期發送的“失效SYN報文”(因網絡延遲滯留)突然到達服務器,服務器會誤以為是新的連接請求,回覆SYN+ACK後直接進入ESTABLISHED狀態,等待客户端發數據。但客户端知道這是失效請求,不會理會,導致服務器一直佔用資源等待,造成浪費。
而三次握手的第三次ACK,能讓服務器確認“客户端確實是要建立新連接”,避免這種“失效連接請求”的干擾——這是TCP可靠性的重要細節。

4. 三次握手的核心意義

  1. 確認雙向收發能力:客户端通過“發SYN→收SYN+ACK”確認服務器“能收能發”;服務器通過“收SYN→發SYN+ACK→收ACK”確認客户端“能收能發”,避免“單向通”問題。
  2. 協商初始序列號:TCP通過序列號(Seq)保證數據按序到達(比如後續發數據會從Seq=x+1、Seq=y+1開始),三次握手階段雙方交換初始序列號,為後續數據傳輸奠定基礎。
  3. 為後續機制鋪路:建立連接後,雙方才能開啓滑動窗口、流量控制等性能優化機制,這些都是TCP高效傳輸的關鍵。

三、TCP四次揮手:如何“安全關閉連接”?

TCP連接是全雙工的——就像電話兩端可以同時説話,客户端和服務器也可以同時向對方發送數據。因此關閉連接時,需要雙方分別確認“我這邊沒有數據要發了”,這就導致了“四次揮手”(三次握手因僅需同步序列號,可合併一次SYN+ACK)。

1. 參與角色與初始狀態

雙方均處於ESTABLISHED狀態(正常通信狀態),某一方(通常是客户端,比如你關閉瀏覽器)先發起關閉請求,成為“主動關閉方”;另一方(服務器)為“被動關閉方”。

2. 四次揮手詳細步驟:像“打電話掛斷”的過程

TCP-三次握手和四次揮手簡單理解_服務器_03

步驟

類比場景(你→朋友)

技術層面(客户端→服務器)

核心數據與標誌位

雙方狀態變化

第一次揮手(“我説完了,你還有要説的嗎?”)

你先説完事情,告訴朋友“我這邊沒話説了”

客户端調用close()函數,發送FIN報文段(結束報文),表示“我已無數據可發”

- 客户端當前序列號(Seq = u,比如u=500,即最後一次發數據的Seq+1)

- 標誌位FIN=1(FIN=Finish,結束請求)

客户端:ESTABLISHEDFIN_WAIT_1(等待服務器確認關閉)

服務器:ESTABLISHEDCLOSE_WAIT(確認收到關閉請求,此時服務器仍可向客户端發數據)

第二次揮手(“好的,我知道你説完了,我再想想還有沒有”)

朋友回覆“聽到了”,但可能還有事情要跟你説

服務器收到FIN後,發送ACK報文段,確認客户端的關閉請求

- 確認號(Ack = u+1 = 501,表示“已收到你Seq=500的FIN”)

- 標誌位ACK=1(確認有效)

服務器:CLOSE_WAIT(繼續發送剩餘數據,比如服務器還沒傳完的網頁內容)

客户端:收到Ack=501後,進入FIN_WAIT_2(等待服務器説“我也説完了”)

第三次揮手(“我也説完了,那掛了吧”)

朋友説完剩餘事情,告訴“我也沒話説了”

服務器發送完所有數據後,調用close(),發送FIN報文段,表示“我也無數據可發”

- 服務器當前序列號(Seq = v,比如v=600,即最後一次發數據的Seq+1)

- 標誌位FIN=1(結束請求)

服務器:CLOSE_WAITLAST_ACK(等待客户端最終確認關閉)

客户端:收到FIN後,進入TIME_WAIT(關鍵狀態,等待2MSL時間)

第四次揮手(“好的,掛吧”)

你回覆“好的”,確認雙方都沒話説了

客户端收到FIN後,發送ACK報文段,最終確認關閉

- 確認號(Ack = v+1 = 601,表示“已收到你Seq=600的FIN”)

- 標誌位ACK=1(最終確認)

客户端:TIME_WAIT(等待2MSL後進入CLOSED

服務器:收到Ack=601後,進入CLOSED(連接完全關閉,釋放資源)

3. 兩個關鍵狀態解析

(1)TIME_WAIT:為什麼要等“2MSL”?
  • MSL(Maximum Segment Lifetime):TCP報文在網絡中的最大生存時間(通常為1-2分鐘),超過這個時間的報文會被網絡丟棄。
  • 2MSL的作用(:
  1. 確保“最後一個ACK”被服務器收到:如果客户端發送的第四次揮手ACK丟失,服務器會重發FIN;2MSL時間足夠客户端收到重發的FIN,並再次發送ACK,避免服務器一直處於LAST_ACK狀態。
  2. 清空網絡中的“殘留報文”:2MSL時間能確保客户端發送的所有報文(包括最後一個ACK)都從網絡中消失,避免後續新連接收到舊連接的殘留報文,導致數據混亂。
(2)CLOSE_WAIT:為什麼服務器會出現大量CLOSE_WAIT?

文檔明確指出:服務器出現大量CLOSE_WAIT,本質是“服務器沒有正確調用close()函數”——服務器收到客户端的FIN後進入CLOSE_WAIT,但因代碼bug(比如忘記關閉socket),一直不發送自己的FIN,導致連接長期滯留在此狀態。
解決方法很簡單:檢查服務器代碼,確保在“無需繼續發送數據”時主動調用close(),釋放socket資源。

4. 為什麼是“四次”而不是“三次”?

因為TCP是全雙工的,關閉連接需要“雙向確認”:

  • 第一次和第二次揮手:客户端確認“我這邊關了”,服務器知道“客户端關了”;
  • 第三次和第四次揮手:服務器確認“我這邊也關了”,客户端知道“服務器關了”。
    如果合併成三次,比如服務器在第二次揮手時同時發送FIN,可能導致服務器還有數據沒發完就強制關閉,造成數據丟失——這違背了TCP可靠傳輸的原則。

四、三次握手與四次揮手對比(一目瞭然)

維度

三次握手(建立連接)

四次揮手(關閉連接)

核心目的

雙向確認收發能力、協商序列號

雙向確認無數據可發、釋放資源

交互次數

3次(含1次SYN+ACK合併)

4次(無合併,全雙工需分別確認)

關鍵標誌位

SYN(同步)、ACK(確認)

FIN(結束)、ACK(確認)

主動方狀態流

CLOSED → SYN_SENT → ESTABLISHED

ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED

被動方狀態流

CLOSED → LISTEN → SYN_RCVD → ESTABLISHED

ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED

資源佔用

建立後佔用socket、緩衝區等資源

關閉過程中逐步釋放資源(TIME_WAIT階段仍佔用少量資源)

五、總結:TCP連接管理的核心邏輯

無論是三次握手還是四次揮手,TCP的設計始終圍繞“可靠”和“高效”兩個關鍵詞:

  • 可靠:通過雙向確認(握手)、狀態監控(TIME_WAIT)、重發機制(丟失ACK重發),確保連接建立和關閉的安全性;
  • 高效:通過合併報文(三次握手中的SYN+ACK)、狀態流轉(避免資源浪費),減少網絡交互次數,提升傳輸效率。

希望通過本文的類比和拆解,你能徹底搞懂TCP三次握手與四次揮手——下次再遇到相關問題,不妨想想“打電話”的場景,很多複雜的技術細節都會變得通俗易懂!