計算機網絡 TCP三次握手、四次揮手超詳細流程【報文交換、狀態變化】

TCP(傳輸控制協議)是互聯網最重要的協議之一,它保證了數據的可靠、有序傳輸。連接建立時的“三次握手”和連接關閉時的“四次揮手”是其核心機制,涉及特定的報文交換和狀態變化。

一、TCP 三次握手(Three-Way Handshake) - 建立連接

目的:同步雙方的初始序列號(Sequence Number,簡稱 Seq),確認對方能夠正常收發數據,建立雙向連接。

狀態變化詳細過程:

  1. CLOSED -> LISTEN(服務器端):
    • 服務器啟動,調用 listen() 進入 LISTEN 狀態,準備接受連接請求。
  2. SYN_SENT(客戶端):
    • 客戶端調用 connect() 主動發起連接請求。
    • 客戶端發送一個 SYN 報文:
      • SYN 標志位設置為 1
      • 隨機生成一個初始序列號 client_seq = x
      • 無確認號(因為還沒收到對方的任何序列號)。
    • 客戶端進入 SYN_SENT 狀態(表示已發送 SYN,等待對方的 SYN+ACK)。
  3. LISTEN -> SYN_RCVD(服務器端):
    • 服務器處于 LISTEN 狀態,接收到客戶端發來的 SYN 報文。
    • 服務器決定接受連接,并發送一個 SYN + ACK 報文:
      • SYN 標志位設置為 1
      • ACK 標志位設置為 1
      • 隨機生成一個初始序列號 server_seq = y
      • 將確認號 ack = x + 1(因為客戶端的 SYN 占用了序列號 x,所以服務器期望收到客戶端發來的下一個數據字節的序列號是 x+1)。
    • 服務器進入 SYN_RCVD 狀態(表示已發送 SYN+ACK,等待客戶的 ACK)。
  4. SYN_SENT -> ESTABLISHED(客戶端):
    • 客戶端處于 SYN_SENT 狀態,收到服務器發來的 SYN + ACK 報文。
    • 客戶端發送一個 ACK 報文:
      • ACK 標志位設置為 1
      • 序列號 seq = x + 1(因為客戶端的 SYN 報文占用了序列號 x,所以下一個報文的序列號是 x+1)。
      • 確認號 ack = y + 1(因為服務器的 SYN 報文占用了序列號 y,所以客戶端期望收到服務器發來的下一個數據字節的序列號是 y+1)。
    • 客戶端進入 ESTABLISHED 狀態(表示連接已建立)。
  5. SYN_RCVD -> ESTABLISHED(服務器端):
    • 服務器處于 SYN_RCVD 狀態,收到客戶端發來的 ACK 報文。
    • 服務器驗證該 ACK 報文的確認號 ack 是否等于 y + 1
    • 驗證通過后,服務器也進入 ESTABLISHED 狀態(表示連接已建立)。

至此,雙向通信通道建立完成。

二、TCP 四次揮手(Four-Way Handshake) - 關閉連接

目的:雙方都確認對方不再發送數據,安全地終止雙向連接。

狀態變化詳細過程:

  1. ESTABLISHED -> FIN_WAIT_1(主動關閉方 - 通常是客戶端):
    • 主動關閉方(A)調用 close() 或進程退出。
    • A 發送一個 FIN 報文:
      • FIN 標志位設置為 1
      • 序列號 seq = u(等于 A 要發送的下一個數據的序列號,但 FIN 消耗一個序列號)。
    • A 進入 FIN_WAIT_1 狀態(表示已發送 FIN,等待對方的 ACK 對方的 FIN)。
  2. ESTABLISHED -> CLOSE_WAIT(被動關閉方):
    • 被動關閉方(B)處于 ESTABLISHED 狀態,收到 A 發來的 FIN 報文。
    • B 知道自己該方向的數據發送通道將被關閉(應用程序會收到 EOF)。
    • B 發送一個 ACK 報文:
      • ACK 標志位設置為 1
      • 序列號 seq = v(B 自己的下一個序列號)。
      • 確認號 ack = u + 1(表示收到了 A 的 FIN 報文)。
    • B 進入 CLOSE_WAIT 狀態(表示收到對方的 FIN,自己的關閉過程開始,等待自己的應用程序通知關閉)。此時:A 到 B 的發送通道已關閉(A不再發送數據),但 B 到 A 的發送通道可能還有數據需要發送。
  3. FIN_WAIT_1 -> FIN_WAIT_2(主動關閉方):
    • A 處于 FIN_WAIT_1 狀態,收到 B 發來的 ACK 報文。
    • A 驗證該 ACK 報文的確認號 ack 是否等于 u + 1
    • 驗證通過后,A 進入 FIN_WAIT_2 狀態(表示已收到對方對 FIN 的 ACK,等待對方發送 FIN)。
  4. CLOSE_WAIT -> LAST_ACK(被動關閉方):
    • B 處于 CLOSE_WAIT 狀態,完成了自己方向的數據發送(應用程序調用 close())。
    • B 發送一個 FIN 報文:
      • FIN 標志位設置為 1
      • 序列號 seq = w(這個序列號可能等于 v(如果 CLOSE_WAIT 期間 B 沒有發數據)或大于 v(如果 B 發過數據))。
      • 確認號 ack 仍然是 u + 1(因為在這個方向上 A 沒有新數據)。
    • B 進入 LAST_ACK 狀態(表示自己已發送 FIN,等待對方最后的 ACK)。
  5. FIN_WAIT_2 -> TIME_WAIT(主動關閉方):
    • A 處于 FIN_WAIT_2 狀態,收到 B 發來的 FIN 報文。
    • A 發送一個 ACK 報文:
      • ACK 標志位設置為 1
      • 序列號 seq = u + 1(之前的 FIN 報文序列號是 u)。
      • 確認號 ack = w + 1(確認 B 的 FIN 報文)。
    • A 進入 TIME_WAIT 狀態(也稱為 2MSL Wait 狀態)。此狀態會持續一段時間(通常為 2 * Maximum Segment Lifetime (MSL),默認在 Linux 中是 60 秒)。
  6. LAST_ACK -> CLOSED(被動關閉方):
    • B 處于 LAST_ACK 狀態,收到 A 發來的 ACK 報文。
    • B 驗證該 ACK 報文的確認號 ack 是否等于 w + 1
    • 驗證通過后,B 關閉連接,進入 CLOSED 狀態。
  7. TIME_WAIT -> CLOSED(主動關閉方):
    • A 在 TIME_WAIT 狀態等待 2MSL 時間。
    • 目的:
      • 確保最后一個 ACK 報文送達 B: 如果 B 沒有收到最后一個 ACK(它在 LAST_ACK 狀態等待),會在超時后重發 FIN。處于 TIME_WAIT 的 A 收到這個重發的 FIN,會再次發送 ACK。
      • 確保網絡中所有舊的報文段消散: 防止具有相同四元組(源IP、源端口、目的IP、目的端口)的下一個新連接,錯誤地接收和處理上一個舊連接的殘留報文。
    • 2MSL 時間到,A 關閉連接,進入 CLOSED 狀態。

至此,連接完全終止。

核心問題解答

為什么需要“三次”握手?兩次握手不行嗎?

不行。 原因主要有:

  1. 避免失效連接請求造成的資源浪費和歷史連接問題:
    • 場景: 假設客戶端發送了第一個 SYN=1 請求(X),但因網絡擁塞嚴重延遲。客戶端超時未收到響應,會重發第二個 SYN=1 請求(Y)。Y 成功到達,服務器響應 SYN+ACK,客戶端也響應 ACK,完成三次握手建立連接。通信結束,連接關閉。
    • 問題: 現在那個延遲了的初始 SYN 請求 X 終于到達了服務器。如果只有兩次握手(服務器收到 SYN -> 響應 SYN+ACK -> 建立連接),服務器會誤以為這是一個新的連接請求(歷史連接),并立即為其分配資源(建立連接表項、分配緩沖區等)。
    • 后果: 服務器資源被無意義占用(因為客戶端此時根本不知道還有這個連接存在,也不會發送數據)。此外,如果這個“幽靈連接”被分配了新的序列號,也可能干擾后續真正的新連接(相同端口復用)。
    • **解決:**三次握手中的第三次握手(ACK)就是客戶端的明確確認信號。 當那個延遲的 SYN 包 X 到達服務器時,服務器會發送 SYN+ACK,但客戶端已經關閉了最初的連接意圖,它會忽略這個 SYN+ACK 或者發送 RST 拒絕。這樣服務器就不會為這個無效請求建立連接。
  2. 初始序列號同步的雙向確認:
    • 通信雙方都需要知道對方的初始序列號。兩次握手只能確保客戶端知道服務器的初始序列號(在服務器的 SYN+ACK 中),并確認服務器的發送能力。但服務器在第二次握手時發送的 SYN+ACK,并未得到客戶端的確認(僅兩次握手的話,服務器在第二步就認為連接建立了)。
    • 問題: 服務器不知道客戶端是否成功收到了自己的序列號 y。如果這個 SYN+ACK 丟失了,服務器認為自己建立了連接(已發送SYN+ACK -> 等待ACK),但客戶端還在等待 SYN+ACK(它沒收到),雙方狀態不一致。
    • **解決:**第三次握手的 **ACK** 報文明確告訴服務器:“我收到了你的初始序列號 **y**,我期望的下一個序列號是 **y+1**”。 這完成了服務器序列號的同步確認。

總結: 三次握手是保證可靠性、防止建立錯誤連接、且完成序列號雙向同步確認的最小開銷方案。

為什么需要“四次”揮手?

主要原因是:TCP 連接是全雙工(Full-Duplex)的。

  1. 雙向獨立的關閉通道:
    • 當客戶端發送 FIN 時,表示它數據發送完畢(不再往服務器寫數據),但服務器到客戶端方向的數據發送通道并未立即關閉。
    • 服務器收到 FIN 后,知道自己該方向的數據接收通道已關閉(收到EOF),但需要檢查自己的應用程序是否還有數據要發送給客戶端。如果還有數據要發送(比如最后要確認客戶端請求操作成功的消息),服務器會在 CLOSE_WAIT 狀態繼續發送這些數據。
    • 只有等待服務器自己也確定所有數據都發送完畢(應用層調用 close())時,它才會發送自己的 FIN 來關閉“服務器->客戶端”方向的發送通道。
    • 因此,關閉連接需要四個步驟:
      • A -> B 發送 FIN:關閉 A 的發送通道。
      • B -> A 發送 ACK:確認收到 A 的 FIN。此時 B 的接收通道關閉(知道 A 不再發數據)。
      • B -> A 發送 FIN:關閉 B 的發送通道。(這條 FIN 的發送時間獨立于前面的 ACK)
      • A -> B 發送 ACK:確認收到 B 的 FIN。
  2. FIN 和 ACK 可能無法合并:
    • 當 B 收到 A 的 FIN 時,它必須立即響應一個 ACK(這是協議要求)。但此時 B 的應用程序可能還未決定關閉/發送完自己的數據(處于 CLOSE_WAIT 狀態),因此 B 的 FIN 報文無法像第二次握手(SYN+ACK)那樣與此時的 ACK 合并發送。ACK 必須在收到 FIN 后立即發送,而 FIN 必須等 B 準備好關閉其發送端時才發送。

總結: 四次揮手是 TCP 全雙工特性決定的。發送 FIN 意味著“我這邊不準備再發送數據了”。兩次揮手只能關閉一個方向(A->B),四次揮手才能徹底關閉兩個獨立的數據發送通道(A->B 和 B->A),確保數據完整性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919197.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919197.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919197.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Applications Manager進行 Apache Solr 監控

Apache Solr 為一些對性能極為敏感的環境提供搜索支持:電子商務、企業應用、內容門戶和內部知識系統。因此,當出現延遲增加或結果不一致的情況時,用戶會立刻察覺。而當這些問題未被發現時,情況會迅速惡化。 Apache Solr 基于 Apa…

Shell腳本-for循環語法結構

一、前言在 Linux Shell 腳本編程中,for 循環 是最常用的控制結構之一,用于重復執行一段命令,特別適用于處理列表、文件、數字序列等場景。本文將詳細介紹 Shell 腳本中 for 循環的各種語法結構,包括:? 經典 for in 結…

記SpringBoot3.x + Thymeleaf 項目實現(MVC架構模式)

目錄 前言 一、創建SpringBoot項目 1. 創建項目 2. 運行項目 二、連接數據庫實現登錄 1. pom.xml文件引入依賴包 2. application.yml文件配置 3. 數據持久層,mybatis操作映射 4. Service接口及實現 5. Controller代碼 6. Thymeleaf頁面登錄 7. 運行項目…

Java 導出word 實現表格內插入圖表(柱狀圖、折線圖、餅狀圖)--可編輯數據

表格內插入圖表導出效果表格內圖表生成流程分析 核心問題與解決方案 問題 Word 圖表作為獨立對象,容易與文本分離位置難以精確控制,編輯時容易偏移缺乏與表格數據的關聯性 解決方案 直接嵌入:將圖表嵌入表格單元格,確保數據關聯精…

北京JAVA基礎面試30天打卡12

1.MySQL中count(*)、count(I)和count(字段名)有什么區別? 1**.COUNT ()**是效率最高的統計方式:COUNT()被優化為常量,直接統計表的所有記錄數,不依賴字段內容,開銷最低。推薦在統計整個表的記錄數時使用。 2.**COUNT(1…

【AI】——結合Ollama、Open WebUI和Docker本地部署可視化AI大語言模型

🎼個人主頁:【Y小夜】 😎作者簡介:一位雙非學校的大三學生,編程愛好者, 專注于基礎和實戰分享,歡迎私信咨詢! 🎆入門專欄:🎇【MySQL&#xff0…

RAG學習(二)

構建索引 一、向量嵌入 向量嵌入(Embedding)是一種將真實世界中復雜、高維的數據對象(如文本、圖像、音頻、視頻等)轉換為數學上易于處理的、低維、稠密的連續數值向量的技術。 想象一下,我們將每一個詞、每一段話、…

亞馬遜店鋪績效巡檢_影刀RPA源碼解讀

一、項目簡介 本項目是一個基于RPA開發的店鋪績效巡店機器人。該機器人能夠自動化地登錄賣家后臺,遍歷多個店鋪和站點,收集并分析各類績效數據,包括政策合規性、客戶服務績效、配送績效等關鍵指標,并將數據整理到Excel報告中&…

跨越南北的養老對話:為培養“銀發中國”人才注入新動能

2025年8月16日,北京養老行業協會常務副會長陳楫寶一行到訪廣州市白云區粵榮職業培訓學校,受到頤年集團副總李娜的熱情接待。此次訪問不僅是京穗兩地養老行業的一次深度交流,更為推動全國智慧養老體系建設、提升養老服務專業化水平注入了新動能…

Spring IOC 學習筆記

1. 概述Spring IOC(Inversion of Control,控制反轉)是一種設計思想,通過依賴注入(Dependency Injection,DI)實現。它的核心思想是將對象的創建和依賴關系的管理交給Spring容器,從而降…

揭開Android Vulkan渲染封印:幀率暴增的底層指令

ps:本文內容較干,建議收藏后反復邊跟進源碼邊思考設計思想。壹渲染管線的基礎架構為什么叫渲染管線?這里是因為整個渲染的過程涉及多道工序,像管道里的流水線一樣,一道一道的處理數據的過程,所以使用渲染管…

HTTP 請求轉發與重定向詳解及其應用(含 Java 示例)

在 Web 開發中,我們經常需要在不同頁面之間跳轉,比如登錄成功后跳到首頁、提交表單后跳到結果頁面。這時,常見的兩種跳轉方式就是 請求轉發(Request Forward) 和 重定向(Redirect)。雖然它們都能…

如何將 MCP Server (FastMCP) 配置為公網訪問(監聽 0.0.0.0)

如何將 MCP Server (FastMCP) 配置為公網訪問(監聽 0.0.0.0)引言常見錯誤嘗試根本原因:從源碼解析正確的解決方案總結引言 在使用 Model Context Protocol(MCP) 框架開發自定義工具服務器時,我們經常使用 …

The Network Link Layer: 無線傳感器中Delay Tolerant Networks – DTNs 延遲容忍網絡

Delay Tolerant Networks – DTNs 延遲容忍網絡架構歸屬Delay Tolerant Networks – DTNs 延遲容忍網絡應用實例例子 1:瑞典北部的薩米人 (Saami reindeer herders)例子 2:太平洋中的動物傳感網絡DTNs路由方式——存儲&轉發DTNs移動模型Random walk …

計算機視覺(opencv)實戰二——圖像邊界擴展cv2.copyMakeBorder()

OpenCV copyMakeBorder() 圖像邊界擴展詳解與實戰在圖像處理和計算機視覺中,有時需要在原始圖像的四周增加邊界(Padding)。這種操作在很多場景中都有應用,比如:卷積神經網絡(CNN)中的圖像預處理…

ansible管理變量和事實

ansible管理變量和事實與實施任務控制 在 Ansible 中,變量和事實(Facts)就像給劇本(Playbook)配備的 “信息工具箱”,讓你的自動化配置管理更靈活、更智能。 變量:提前準備的 “預設信息” 變…

STM32--寄存器與標準庫函數--基本定時器

目錄 前言 基本定時器概念 定時時間 定時器時鐘確定 倍頻鎖相環被正確配置為168MHz 定時器的庫函數操作 代碼 定時器的寄存器操作 代碼 寄存器 后言 前言 使用平臺:STM32F407ZET6 使用數據手冊:STM32F407數據手冊.pdf 使用參考手冊&…

PCA 實現多向量壓縮:首個主成分的深層意義

PCA 實現多向量壓縮 第一個主成分(components_[0])正是數據協方差矩陣中最大特征值對應的特征向量。 ,layer_attention_vector[layer] 被賦值為 pca.components_[0],這確實是一個特征向量,具體來說是 PCA 分解得到的第一個主成分(主特征向量)。 關于它的維度: 假設 c…

網絡常識-DNS如何解析

DNS(Domain Name System,域名系統)是互聯網的“地址簿”,負責將人類易記的域名(如www.example.com)轉換為計算機可識別的IP地址(如192.168.1.1)。其工作流程可以簡單理解為“從域名到…

Java中 23 種設計模式介紹,附帶示例

文章目錄設計模式六大原則設計模式分類1、創建型模式(Creational Patterns)2、結構型模式(Structural Patterns)3、行為型模式(Behavioral Patterns)一、創建型模式(Creational Patterns&#x…