跳转至

HTTP 握手

HTTP 本身没有应用层握手,但底层的 TCP 和 TLS 各自有独立的握手流程


核心概念

  1. TCP 三次握手 — 所有 HTTP 连接建立前的基础,客户端与服务器确认彼此收发能力
  2. TLS 握手 — HTTPS 场景下在 TCP 之上完成密钥协商和证书验证
  3. HTTP/2 SETTINGS 交换 — 应用层的"半个握手",双方协商连接参数
  4. QUIC 握手 — HTTP/3 将传输层和加密层合二为一,一次握手同时完成建连和加密

详解

TCP 三次握手

每次 HTTP 通信之前,底层都要先完成 TCP 三次握手:

sequenceDiagram
    participant C as 客户端
    participant S as 服务器
    C->>S: SYN(我要连接)
    S->>C: SYN-ACK(收到,我也准备好了)
    C->>S: ACK(确认,开始传数据)
阶段 方向 标志位 作用
第一次 客户端 → 服务器 SYN 客户端发起连接请求
第二次 服务器 → 客户端 SYN-ACK 服务器确认并回应
第三次 客户端 → 服务器 ACK 客户端确认,连接建立

三次握手的本质是**双方各确认一次收发能力**,确保连接可靠。

TLS 握手(HTTPS)

在 TCP 握手之后、HTTP 请求之前完成:

TLS 版本 握手耗时 说明
TLS 1.2 2-RTT(两个来回) 需要两次往返完成密钥协商
TLS 1.3 1-RTT(一个来回) 优化了握手流程
TLS 1.3 0-RTT 0-RTT 恢复会话时无需额外往返

TLS 握手完成的事:

  • 证书验证:确认服务器身份,防止中间人攻击
  • 密钥协商:生成对称加密密钥
  • 加密套件确定:双方商定使用的加密算法

HTTP/1.0 和 HTTP/1.1

这两个版本**没有应用层握手**——TCP 连上、TLS 握完,直接发 HTTP 请求。

# TCP 连接建立后,直接发请求
GET /index.html HTTP/1.1
Host: example.com

HTTP/2 的 SETTINGS 交换

HTTP/2 在连接建立后有一个应用层初始化过程:

sequenceDiagram
    participant C as 客户端
    participant S as 服务器
    Note over C,S: TCP + TLS 握手完成
    C->>S: SETTINGS 帧(我的能力参数)
    S->>C: SETTINGS 帧(我的能力参数)
    C->>S: SETTINGS ACK
    S->>C: SETTINGS ACK
    Note over C,S: 可以开始发送请求了

双方通过 SETTINGS 帧交换参数,如最大并发流数、窗口大小等。这不算严格的"握手",但起到类似的协商作用。

HTTP/3 (QUIC)

HTTP/3 基于 QUIC 协议,QUIC 运行在 UDP 之上:

graph LR
    A[QUIC] --> B[内置 TLS 1.3]
    A --> C[内置可靠传输]
    A --> D[多路复用]
    A --> E[0-RTT 恢复]
  • QUIC 把传输层握手和 TLS 1.3 握手**合二为一**
  • 首次连接只需 1-RTT
  • 恢复连接可达 0-RTT
  • 解决了 TCP 的队头阻塞问题(单个流丢包不影响其他流)

各层握手对比

层级 协议 有握手? 耗时
传输层 TCP ✅ 三次握手 1-RTT
安全层 TLS 1.2 ✅ 密钥协商 2-RTT
安全层 TLS 1.3 ✅ 密钥协商 1-RTT
应用层 HTTP/1.x ❌ 无 —
应用层 HTTP/2 半个(SETTINGS) ~0.5-1 RTT
传输+安全 HTTP/3 (QUIC) ✅ 内置 TLS 1.3 1-RTT / 0-RTT

常见陷阱

误区:认为 HTTPS 只多了一次握手

HTTPS 的额外开销不仅是 TLS 握手本身。如果 CDN、代理层多,TLS 握手可能要打好几次。理解每一层的握手才能优化延迟。

0-RTT 并非免费

TLS 1.3 的 0-RTT 恢复虽然快,但存在**重放攻击**风险。0-RTT 发送的数据不能保证幂等性,因此不适合做敏感操作(如支付)。


练习题

为什么 TCP 握手是三次而不是两次?
答案

两次握手无法防止**已失效的连接请求**到达服务器。如果客户端的旧 SYN 延迟到达,服务器会误以为是新请求并建立连接,白白浪费资源。三次握手让客户端有最后一次确认的机会,丢弃过期请求。

HTTP/2 的 SETTINGS 交换和 TCP 三次握手有什么区别?
答案

TCP 三次握手发生在传输层,目的是建立可靠的字节流通道。HTTP/2 的 SETTINGS 交换发生在应用层,目的是协商 HTTP 协议参数(如最大并发流、窗口大小等)。TCP 握手解决的是"能不能通信",SETTINGS 解决的是"怎么高效通信"。