深度解析 TCP 三次握手與四次揮手:從原理到 HTTP/HTTPS 的應用

TCP 的三次握手和四次揮手是網絡通信的基石,無論是 HTTP 還是 HTTPS,它們都依賴 TCP 提供可靠的傳輸層服務。本文將用萬字篇幅,結合 Mermaid 圖表和代碼示例,深入講解 TCP 三次握手、四次揮手的原理、過程、狀態變化,以及它們在 HTTP 和 HTTPS 中的應用場景。無論你是網絡新手還是想深入理解 TCP 的開發者,這篇文章都會帶你全面掌握這些核心機制!

1. TCP 協議概述

TCP(Transmission Control Protocol,傳輸控制協議)是互聯網協議棧中的傳輸層協議,旨在提供可靠的、面向連接的、字節流傳輸服務。它確保數據包按序到達、無丟失、無重復,廣泛應用于 HTTP、HTTPS、FTP 等協議。

TCP 的核心特性

  • 可靠性:通過序列號、確認機制和重傳機制保證數據完整性。
  • 面向連接:通信前通過三次握手建立連接,通信后通過四次揮手斷開連接。
  • 流量控制:通過滑動窗口避免發送方過載接收方。
  • 擁塞控制:通過算法(如慢啟動、擁塞避免)適應網絡狀況。

TCP 在協議棧中的位置

應用層: HTTP/HTTPS
傳輸層: TCP
網絡層: IP
數據鏈路層
物理層

圖表說明

  • HTTP/HTTPS 運行在應用層,依賴 TCP 提供可靠傳輸。
  • TCP 封裝數據為段(Segment),交給 IP 層傳輸。

2. TCP 三次握手詳解

三次握手(Three-Way Handshake)是 TCP 建立連接的過程,確保雙方準備好通信并協商初始序列號。它包含三次數據包交互,涉及客戶端和服務器之間的狀態轉換。

2.1 三次握手的流程

三次握手的目的是建立可靠的連接,確保雙方都能發送和接收數據,同時初始化序列號以跟蹤數據傳輸。

三次握手流程圖

客戶端服務器SYN (seq=x)服務器: LISTEN ->> SYN_RECEIVEDSYN+ACK (seq=y, ack=x+1)客戶端: SYN_SENT ->> ESTABLISHEDACK (ack=y+1)服務器: SYN_RECEIVED ->> ESTABLISHED數據傳輸客戶端服務器

流程詳解

  1. 第一次握手(SYN)

    • 客戶端發送 SYN(Synchronize)包,包含初始序列號 seq=x
    • 客戶端進入 SYN_SENT 狀態,等待服務器響應。
    • 目的:通知服務器客戶端希望建立連接,并提供初始序列號。
  2. 第二次握手(SYN+ACK)

    • 服務器收到 SYN 包,回復 SYN+ACK 包,包含自己的初始序列號 seq=y 和確認號 ack=x+1
    • 服務器從 LISTEN 狀態進入 SYN_RECEIVED 狀態。
    • 目的:確認收到客戶端的 SYN,并表明服務器也準備好通信。
  3. 第三次握手(ACK)

    • 客戶端收到 SYN+ACK 包,回復 ACK 包,包含確認號 ack=y+1
    • 客戶端進入 ESTABLISHED 狀態,服務器收到 ACK 后也進入 ESTABLISHED 狀態。
    • 目的:確認雙方都已準備好,連接正式建立。

狀態轉換圖

服務器啟動
客戶端發送 SYN
收到 SYN,發送 SYN+ACK
收到 SYN+ACK,發送 ACK
收到 ACK
CLOSED
LISTEN
SYN_SENT
SYN_RECEIVED
ESTABLISHED
style
#FF6384
#36A2EB
#FFCE56
#4BC0C0
#36A2EB

關鍵點

  • 為什么需要三次握手?
    • 確保雙方都能發送和接收數據(雙向通信)。
    • 同步初始序列號,避免舊連接干擾。
    • 防止因網絡延遲導致的錯誤連接(如重復的 SYN 包)。
  • 序列號的作用
    • TCP 使用序列號(Sequence Number)跟蹤數據段的順序。
    • 確認號(Acknowledgment Number)表示期望接收的下一個字節。

2.2 三次握手的代碼模擬

以下是使用 Node.js 的簡單代碼模擬三次握手的概念(實際 TCP 握手由操作系統內核處理):

const net = require('net');// 服務器端
const server = net.createServer((socket) => {console.log('客戶端發起連接 (SYN)');socket.write('SYN+ACK', () => {console.log('服務器響應 SYN+ACK');});socket.on('data', (data) => {if (data.toString() === 'ACK') {console.log('客戶端確認 ACK,連接建立');socket.write('歡迎開始數據傳輸!');}});
});server.listen(8080, () => {console.log('服務器監聽中 (LISTEN)');
});// 客戶端
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {console.log('客戶端發送 SYN');client.write('SYN');
});client.on('data', (data) => {if (data.toString() === 'SYN+ACK') {console.log('收到 SYN+ACK,發送 ACK');client.write('ACK');} else {console.log('收到數據:', data.toString());}
});

運行結果

  1. 服務器啟動,進入 LISTEN 狀態。
  2. 客戶端發送 SYN,模擬第一次握手。
  3. 服務器響應 SYN+ACK,模擬第二次握手。
  4. 客戶端發送 ACK,模擬第三次握手,連接建立。

優化建議

  • 在實際應用中,TCP 握手由操作系統內核完成,開發者無需手動實現。
  • 確保服務器監聽端口未被占用,避免握手失敗。

3. TCP 四次揮手詳解

四次揮手(Four-Way Handshake)是 TCP 斷開連接的過程,確保雙方有序關閉連接,避免數據丟失。

3.1 四次揮手的流程

四次揮手的目的是安全關閉連接,確保雙方都完成數據發送并確認對方已收到。

四次揮手流程圖

客戶端服務器FIN (seq=x)服務器: ESTABLISHED ->> CLOSE_WAITACK (ack=x+1)客戶端: FIN_WAIT_1 ->> FIN_WAIT_2FIN (seq=y)客戶端: FIN_WAIT_2 ->> TIME_WAITACK (ack=y+1)服務器: CLOSE_WAIT ->> CLOSED客戶端: TIME_WAIT ->> CLOSED客戶端服務器

流程詳解

  1. 第一次揮手(FIN)

    • 客戶端(或服務器)發送 FIN(Finish)包,包含序列號 seq=x,表示不再發送數據。
    • 客戶端進入 FIN_WAIT_1 狀態。
    • 目的:通知對方客戶端希望關閉連接。
  2. 第二次揮手(ACK)

    • 服務器收到 FIN,回復 ACK 包,包含確認號 ack=x+1
    • 服務器進入 CLOSE_WAIT 狀態,客戶端進入 FIN_WAIT_2 狀態。
    • 目的:確認收到客戶端的 FIN,允許服務器繼續發送未完成的數據。
  3. 第三次揮手(FIN)

    • 服務器發送完剩余數據后,發送 FIN 包,包含序列號 seq=y
    • 服務器進入 LAST_ACK 狀態。
    • 目的:通知客戶端服務器也準備關閉連接。
  4. 第四次揮手(ACK)

    • 客戶端收到 FIN,回復 ACK 包,包含確認號 ack=y+1
    • 客戶端進入 TIME_WAIT 狀態,等待一段時間(通常 2MSL,最大段生存時間)后進入 CLOSED 狀態。
    • 服務器收到 ACK 后進入 CLOSED 狀態。
    • 目的:確認雙方都完成關閉,避免殘留數據包干擾。

狀態轉換圖

客戶端發送 FIN
收到 ACK
收到 FIN,發送 ACK
發送 FIN
收到 FIN,發送 ACK
收到 ACK
等待 2MSL
ESTABLISHED
FIN_WAIT_1
FIN_WAIT_2
CLOSE_WAIT
LAST_ACK
TIME_WAIT
CLOSED
style
#36A2EB
#FFCE56
#4BC0C0
#FF6384
#36A2EB
#FFCE56
#4BC0C0

關鍵點

  • 為什么需要四次揮手?
    • TCP 是全雙工通信,雙方需要分別關閉發送方向的連接。
    • 四次揮手確保雙方都完成數據發送并確認。
  • TIME_WAIT 的作用
    • 防止舊連接的數據包干擾新連接。
    • 確保服務器收到最后的 ACK,避免服務器無限等待。
  • 2MSL 等待時間
    • MSL(Maximum Segment Lifetime)是數據包在網絡中的最大存活時間。
    • 2MSL 確保網絡中殘留的數據包失效。

3.2 四次揮手的代碼模擬

以下是 Node.js 模擬四次揮手的概念(簡化版):

const net = require('net');// 服務器
const server = net.createServer((socket) => {socket.on('data', (data) => {if (data.toString() === 'FIN') {console.log('收到客戶端 FIN,發送 ACK');socket.write('ACK');setTimeout(() => {console.log('服務器發送 FIN');socket.write('FIN');}, 1000); // 模擬服務器處理剩余數據} else if (data.toString() === 'ACK') {console.log('收到客戶端 ACK,服務器關閉連接');socket.end();}});
});server.listen(8080, () => {console.log('服務器監聽中');
});// 客戶端
const client = new net.Socket();
client.connect(8080, '127.0.0.1', () => {console.log('客戶端發送 FIN');client.write('FIN');
});client.on('data', (data) => {if (data.toString() === 'ACK') {console.log('收到服務器 ACK');} else if (data.toString() === 'FIN') {console.log('收到服務器 FIN,發送 ACK');client.write('ACK');setTimeout(() => {console.log('客戶端進入 TIME_WAIT,關閉連接');client.end();}, 2000); // 模擬 2MSL 等待}
});

運行結果

  1. 客戶端發送 FIN,模擬第一次揮手。
  2. 服務器響應 ACK,模擬第二次揮手。
  3. 服務器發送 FIN,模擬第三次揮手。
  4. 客戶端響應 ACK,進入 TIME_WAIT,模擬第四次揮手。

4. TCP 在 HTTP 和 HTTPS 中的應用

HTTP 和 HTTPS 都基于 TCP 提供可靠傳輸,下面分析它們如何利用三次握手和四次揮手。

4.1 HTTP 與 TCP

HTTP(HyperText Transfer Protocol)是應用層協議,運行在 TCP 之上,用于傳輸網頁內容。

HTTP 請求流程圖

客戶端服務器三次握手SYNSYN+ACKACKHTTP 請求GET /index.html200 OK, HTML 數據四次揮手FINACKFINACK客戶端服務器

關鍵點

  • 短連接(HTTP/1.0):每次請求都需要新的 TCP 連接(三次握手 + 四次揮手),開銷較大。
  • 長連接(HTTP/1.1):通過 Connection: keep-alive,在同一 TCP 連接上復用多個請求,減少握手開銷。

代碼示例(HTTP 長連接)

GET /index.html HTTP/1.1
Host: example.com
Connection: keep-alive

優化建議

  • 使用 HTTP/1.1 或 HTTP/2 的長連接減少 TCP 握手次數。
  • 合并請求(如 CSS Sprites)減少連接需求。

4.2 HTTPS 與 TCP

HTTPS(HTTP Secure)在 HTTP 基礎上通過 TLS/SSL 提供加密通信,但仍依賴 TCP。

HTTPS 連接流程圖

客戶端服務器三次握手SYNSYN+ACKACKTLS 握手Client HelloServer Hello, CertificateKey Exchange, Change Cipher SpecChange Cipher SpecHTTP 請求GET /index.html (加密)200 OK, HTML 數據 (加密)四次揮手FINACKFINACK客戶端服務器

關鍵點

  • TLS 握手:在 TCP 三次握手后,HTTPS 額外進行 TLS 握手,協商加密算法和密鑰。
  • 性能開銷:TLS 握手增加延遲,但通過會話復用(Session Resumption)可優化。
  • 四次揮手:與 HTTP 相同,HTTPS 在數據傳輸完成后通過四次揮手關閉連接。

優化建議

  • 使用 TLS 1.3,減少握手輪次。
  • 啟用會話復用(如 Session Tickets)減少 TLS 握手開銷。
  • 使用 HSTS(HTTP Strict Transport Security)強制 HTTPS。

5. TCP 常見問題與優化

5.1 三次握手的問題

  • SYN 洪水攻擊

    • 攻擊者發送大量 SYN 包但不完成第三次握手,導致服務器資源耗盡。
    • 防御:使用 SYN Cookie,限制半連接隊列大小。
  • 延遲影響

    • 三次握手增加初次連接的延遲,特別是在高延遲網絡中。
    • 優化:使用 TCP Fast Open(TFO),在第一次握手時攜帶數據。

5.2 四次揮手的問題

  • TIME_WAIT 堆積

    • 客戶端在 TIME_WAIT 狀態等待 2MSL,可能導致端口耗盡。
    • 優化:調整系統參數(如 tcp_tw_reuse),或使用長連接減少揮手。
  • 半關閉狀態

    • 服務器在 CLOSE_WAIT 狀態停留時間過長,可能因未及時發送 FIN。
    • 優化:確保服務器及時關閉連接。

問題與優化對比圖

問題
SYN 洪水攻擊
TIME_WAIT 堆積
優化
SYN Cookie
TCP Fast Open
長連接

6. 完整流程總覽

以下是 TCP 三次握手、四次揮手以及 HTTP/HTTPS 應用的完整流程圖,清晰展示整個通信過程。

完整通信流程圖

sequenceDiagramparticipant C as 客戶端participant S as 服務器Note over C,S: 三次握手C->>S: SYN (seq=x)S->>C: SYN+ACK (seq=y, ack=x+1)C->>S: ACK (ack=y+1)Note over C,S: HTTPS: TLS 握手C->>S: Client HelloS->>C: Server Hello, CertificateC->>S: Key Exchange, Change Cipher SpecS->>C: Change Cipher SpecNote over C,S: HTTP/HTTPS 數據傳輸C->>S: GET /index.html (加密)S->>C: 200 OK, HTML 數據 (加密)Note over C,S: 四次揮手C->>S: FIN (seq=x)S->>C: ACK (ack=x+1)S->>C: FIN (seq=y)C->>S: ACK (ack=y+1)style C fill:#36A2EBstyle S fill:#FFCE56

圖表說明

  • 三次握手:建立 TCP 連接,初始化序列號。
  • TLS 握手:HTTPS 額外協商加密參數。
  • 數據傳輸:HTTP/HTTPS 請求和響應。
  • 四次揮手:有序關閉連接,確保數據完整性。

7. 總結

TCP 的三次握手和四次揮手是網絡通信的基石,確保了可靠的連接建立和關閉。HTTP 和 HTTPS 依賴 TCP 提供穩定傳輸,HTTPS 額外通過 TLS 握手實現加密。三次握手同步序列號,四次揮手確保數據發送完成,結合 Mermaid 圖表和代碼示例,我們清晰地展示了這些機制的原理和應用場景。

通過優化(如長連接、TLS 1.3、TCP Fast Open),我們可以顯著提升網絡性能。希望這篇文章能讓你深入理解 TCP 握手與揮手機制,并在開發中更高效地應用 HTTP 和 HTTPS!

點個收藏,關注前端結城,一起用代碼點亮前端世界!🚀

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

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

相關文章

Hyper-V + Centos stream 9 搭建K8s集群(一)

一、創建虛擬機一臺32G內存,16核心的Win11,已經安裝了Hyper-V 管理器。然后也下載了CentOS-Stream-9-latest-x86_64-dvd1.iso的鏡像文件。這里Hyper-V創建虛擬機的過程就不贅述了,如果出現虛擬機加載不到鏡像的問題,先把這個使用安…

Pygame如何制作小游戲

以下是 Pygame 的詳細使用指南,從安裝到開發完整游戲的步驟說明,包含代碼示例和最佳實踐: 一、安裝與環境配置 1. 安裝 Pygame pip install pygame2. 驗證安裝 import pygame pygame.init() print(pygame.version.ver) # 應輸出版本號&am…

@【JCIDS】【需求論證】聯合能力集成與開發系統知識圖譜

JCIDS(聯合能力集成與開發系統)知識圖譜 1. JCIDS概述 2. JCIDS的提出背景 3. JCIDS核心流程 4. JCIDS分析方法 5. JCIDS優勢 6. JCIDS與采辦系統的關系 7. JCIDS知識圖譜結構 8. 對我的啟示 9.JCIDS(聯合能力集成與開發系統)相關術語列表 10. 參考文獻 1. JCIDS概述 定義:…

每天學一個Linux命令(38):vi/vim

每天學一個 Linux 命令(38):vi/vim vi 和 vim(Vi IMproved)是 Linux 和 Unix 系統中功能強大的文本編輯器。vim 是 vi 的增強版,提供語法高亮、多級撤銷、插件支持等更多功能。掌握 vi/vim 是 Linux 系統管理員的必備技能之一。 1. 命令簡介 vi:經典的文本編輯器,幾乎…

【PZ-ZU49DR-KFB】:璞致電子 UltraScale+ RFSoC 架構下的軟件無線電旗艦開發平臺

璞致電子 PZ-ZU49DR-KFB 開發板基于 Xilinx ZYNQ UltraScale RFSoC XCZU49DR 主控制器,以 "ARMFPGA 異構架構" 為核心,融合高帶寬信號采集、高速數據處理與靈活擴展能力,專為專業工程師打造的軟件無線電(SDR&#xff09…

力扣106:從中序與后序遍歷序列構造二叉樹

力扣106:從中序與后序遍歷序列構造二叉樹題目思路代碼題目 給定兩個整數數組 inorder 和 postorder ,其中 inorder 是二叉樹的中序遍歷, postorder 是同一棵樹的后序遍歷,請你構造并返回這顆 二叉樹 。 思路 我們首先要知道中序遍歷和后序…

IDEA JAVA工程入門

Maven配置: IDEA -> settings -> Build, Execution, Deployment -> Build Tools -> MavenMaven home pathUser setting file : 特定倉庫下載依賴包,自動下載(界面右邊M圖標點開,)local repository (本地倉庫&#xff…

Spring依賴注入:從原理到實踐的自學指南

Spring依賴注入:從原理到實踐的自學指南 一、什么是依賴注入? 依賴注入(Dependency Injection, DI)是Spring框架實現控制反轉(IoC)的核心手段。其核心思想是:對象不再自己創建依賴項&#xff…

3_軟件重構_組件化開發實例方法論

1、上期回顧上次內容核心的地方有兩個,①是C多態基類的指針指向派生類,用于初始化各個插件。②是使用C語言的dlopen函數“動態加載”各個插件,實現用戶根據契約接口自定義開發插件,極大程度地實現了軟件上的解耦。③再進一步&…

C#接口的定義與使用

第1章 接口(interface)是什么1.1 定義? 接口是一組“能力”或“契約”的抽象描述,只規定“能做什么”,不規定“怎么做”。? 在 C# 中,接口是一種完全抽象的類型(fully abstract type)。 ? 關…

【STM32】HAL庫中的實現(三):PWM(脈沖寬度調制)

🔧 HAL庫中的實現:PWM(脈沖寬度調制) PWM(Pulse Width Modulation)是基于定時器(TIM)產生的周期性脈沖信號,廣泛應用于:① 電機調速;② LED 亮度控…

GitHub 趨勢日報 (2025年08月03日)

🚀 GitHub 趨勢日報 (2025年08月03日) 📊 由 TrendForge 系統生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日報中的項目描述已自動翻譯為中文 📈 今日獲星趨勢圖 今日獲星趨勢圖751dyad362LLMs-from-scratch291…

Java后端高頻面試題

Java后端高頻面試題 目錄 Java集合框架Java并發編程JVM相關MySQL數據庫Redis緩存Spring框架 Java集合框架 HashMap的數據結構是什么,為什么在JDK8要引入紅黑樹? HashMap數據結構: JDK7:數組 鏈表JDK8:數組 鏈表…

37. line-height: 1.2 與 line-height: 120% 的區別

概述 line-height 是 CSS 中用于控制文本行間距的重要屬性。雖然 line-height: 1.2 和 line-height: 120% 看似相同,但它們在計算方式上存在關鍵區別,尤其是在繼承和計算值方面。1. 計算方式不同寫法類型計算方式說明line-height: 1.2無單位(…

藍橋杯----DS1302實時時鐘

(六)、DS1302實時時鐘1、原理(圖 二十六)DS1302通過三線串行接口與單片機進行通信。微控制器可以通過設置RST引腳為高電平來使能DS1302,并通過SCK引腳提供串行時鐘信號,然后通過I/O引腳進行數據的讀寫操作。…

C++對象訪問有訪問權限是不是在ide里有效

在C中,對象的訪問權限(即公有(public)、保護(protected)和私有(private)成員的訪問)是編譯時的一部分,而不是運行時。這意味著,無論是在IDE&#…

CubeMX安裝芯片包

1.點擊HELP2.選擇公理嵌入式軟件包3.選擇并下載芯片包

【面向對象】面向對象七大原則

設計模式 設計模式是什么? 設計模式是一種針對于反復提出問題的解決方案,是經過長時間經驗和試錯而總結出來的一套業務流程; 其目的是為了提高代碼的可重用性和可維護性,讓代碼更容易讓人理解,保證代碼可靠性&#…

《計算機“十萬個為什么”》之 面向對象 vs 面向過程:編程世界的積木與流水線

《計算機“十萬個為什么”》之 面向對象 vs 面向過程:編程世界的積木與流水線 🤖 想象你要造一輛汽車🔧: 面向過程 按手冊一步步擰螺絲:擰緊螺栓A → 安裝輪胎B → 焊接車架C 面向對象 召喚汽車人戰隊:引…

Visual Studio Code (VSCode) 的常用快捷鍵

Visual Studio Code (VSCode) 的常用快捷鍵可極大提升開發效率。以下是分類整理的 **核心快捷鍵**(基于 **Windows/Linux** 系統,macOS 用戶將 Ctrl 替換為 Cmd,Alt 替換為 Option):? 基礎操作快捷鍵功能Ctrl N新建文…