HTTP 协议

HTTP 协议

目录


HTTP/1.0 {#http10}

multipart/form-data

multipart/form-data 是 HTTP 协议中用于上传文件或表单数据的一种编码格式。

示例:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

HTTP/2.0 {#http20}

HTTP/2.0 的主要特性包括:

  1. 引入逻辑概念 Stream:一个 TCP 连接可以被多个 Stream 共享,每个 Stream 上都可以跑单独的请求/应答,从而实现了 TCP 连接的复用,即单个 TCP 连接上可以并行的传输多个请求/应答,如下图所示

HTTP/2.0 Stream 复用

  1. 改为二进制协议:使得协议更紧凑
  2. 支持协议头的压缩:大大减少了协议头传输带来的开销
  3. 支持 Server 端的 Push:进一步减少了交互流程
  4. 支持流量控制:并引入了流的优先级、依赖关系,允许对流量和资源进行较为细致的控制

Stream(流)的定义和特性

一个 Stream 表示一个独立的、双向的、在 Client 和 Server 之间的 Frame(帧)交换序列。

Stream 具有如下性质:

  1. 一个 HTTP/2 连接可以包含多个并发打开的流,任何一端都可以和多个流交错通信
  2. 流可以由任一端点开启和关闭
  3. 在流上发送帧的顺序是重要的,接受端按接收的顺序处理帧。尤其是,HEADER 和 DATA 帧的顺序在语义上是有意义的
  4. 流由整数标识(Stream Id),流标识符由启动流的端点分配,并且约定,由 Client 端(浏览器)初始化的流,Id 为奇数,由 Server 端(WebServer)初始化的流,Id 为偶数,0 被保留用作整个 TCP 连接的标识

Frame(帧)

Frame(帧)是 HTTP/2 协议传输的最小单位,帧是二进制结构的。详细定义如下:

HTTP/2 Frame 结构

  • Length:24bit 的无符号整数,标识 Payload 的长度(不包括头本身)
  • Type:帧的类型,常见的类型有:
  • 0x0 – DATA:数据帧,用来承载请求的包体
  • 0x1 – HEADERS:包头帧,用来承载请求的包头
  • 0x3 – RST_STREAM:用来强行关闭流,类似 TCP 中的 RST
  • 0x4 – SETTINGS:用来交换一些参数的设置
  • 0x5 – PUSH_PROMISE:用于 Server 端推送
  • 0x6 – PING:保活
  • 0x8 – WINDOW_UPDATE:用于流量控制
  • Flags:一些标识位,具体定义和 Type 相关,一些常见的定义如下:
  • 对于 PING,0x0 表示请求,0x1 表示是应答
  • 对于 SETTINGS,0x1 表示确认和应用了对端发过来的设置参数,此时 payload 必须为空
  • 对于 HEADERS,0x1(END_STREAM),也就是发送端关闭流;0x4(END_HEADERS)表示本 header block(头部压缩序列化后的二进制流)已经发送完成了
  • 对于 DATA,0x1(END_STREAM),表示关闭流
  • R:一个保留 bit,目前没有意义,必须为 0
  • Stream Identifier:Stream 的 id,是 31bit 的无符号整数,由 client 初始化的 stream 必须为奇数,由 server 端初始化的 stream 必须为偶数。0 被保留,用于连接的控制消息,不允许使用 0 作为新建 stream 的 id
  • Payload:依据 Type 有不同的结构和含义

HTTP 的请求和应答消息

一个 HTTP 的请求/应答消息由如下部分顺序组成:

  • 对于应答消息,可以有 0 个或多个 HEADERS 帧,包含通知类的 HTTP 头(状态码 1xx)
  • 一个 HEADERS 帧(允许包含 0 个或多个 CONTINUATION 帧)包含消息头信息
  • 0 个或多个 DATA 帧,包含消息的 PayLoad
  • 可选的,可以在消息尾包含一个 HEADERS 帧(允许跟随 CONTINUATION 帧)
  • 这些帧序列的最后一个,必须有 END_STREAM 标识,用来结束这个 Stream
  • HEADERS 帧只允许出现在流的开头和结尾

HTTP/3.0 {#http30}

HTTP/3.0 是 HTTP 协议的最新版本,其最大的变化是放弃了 TCP 协议,改用基于 UDP 的 QUIC(Quick UDP Internet Connections)协议。

为什么要使用 QUIC

HTTP/2.0 虽然通过多路复用解决了应用层的队头阻塞问题,但仍然受制于 TCP 协议本身的队头阻塞:当一个 TCP 数据包丢失时,所有后续数据包都必须等待该包重传,即使这些数据属于不同的 HTTP 流。

QUIC 协议的主要优势:

  1. 彻底解决队头阻塞:QUIC 在传输层实现了独立的流,一个流的丢包不会影响其他流
  2. 更快的连接建立:QUIC 将传输层握手和加密握手合并,通常只需 1-RTT 即可建立连接,0-RTT 可用于恢复连接
  3. 连接迁移:QUIC 使用连接 ID 而非四元组(源 IP、源端口、目标 IP、目标端口)标识连接,因此在网络切换(如 WiFi 到 4G)时无需重新建立连接
  4. 内置加密:QUIC 强制使用 TLS 1.3,加密是协议的一部分而非可选项

QUIC 的丢包重传机制

QUIC 采用了类似 TCP 但更优化的丢包检测和重传机制:

1. 丢包检测方式

QUIC 通过两种方式检测丢包:

  • 基于 ACK 的检测:当收到后续数据包的 ACK,但某个数据包仍未被确认时,该数据包被标记为丢失
  • 默认阈值:当比它大的 3 个 Packet Number 都被确认后,认为该包丢失(类似 TCP 的快速重传)

  • 基于超时的检测:使用 PTO(Probe Timeout)机制

  • 如果在预期时间内未收到 ACK,触发超时重传
  • PTO 时间根据平滑 RTT(Smoothed RTT)和 RTT 变化(RTT Variation)动态计算

2. 单调递增的 Packet Number

QUIC 的关键创新是每个数据包都有唯一的 Packet Number,即使是重传:

原始发送: Packet #10, Stream 5, Offset 0-999
丢失检测后重传: Packet #25, Stream 5, Offset 0-999  (使用新的 Packet Number)

优势:
– 消除了 TCP 重传歧义问题(Retransmission Ambiguity)
– 可以精确测量每个数据包的 RTT,优化拥塞控制算法

3. ACK Frame 机制

QUIC 的 ACK Frame 可以确认多个不连续的 Packet Number 范围:

ACK Frame 示例:
Largest Acknowledged: 100
ACK Ranges:
  [98-100]  (收到)
  [95-96]   (收到)
  [90-92]   (收到)

未确认: 93-94, 97  (需要重传)

4. 流级别的独立重传

  • 每个 Stream 独立管理自己的数据偏移(Offset)
  • Stream A 的丢包重传不会阻塞 Stream B 的数据交付
  • 这是 QUIC 解决 TCP 队头阻塞的核心机制

HTTP/3 的主要特性

  1. 基于 QUIC 传输:所有 HTTP/3 连接都运行在 QUIC 之上,继承了 QUIC 的所有优势
  2. 保留 HTTP/2 的优点
  3. 二进制协议
  4. 头部压缩(使用改进的 QPACK 算法,解决了 HPACK 的队头阻塞问题)
  5. 多路复用
  6. Server Push(虽然在实践中较少使用)
  7. 更好的性能:在弱网环境下,HTTP/3 相比 HTTP/2 有显著的性能提升

协议发现机制

由于 HTTP/3 使用 UDP 而非 TCP,客户端如何知道服务器支持 HTTP/3?

  1. Alt-Svc 头:服务器在 HTTP/1.1 或 HTTP/2 响应中返回 Alt-Svc 头,告知客户端可以通过 QUIC 访问
    Alt-Svc: h3=":443"; ma=2592000
  2. DNS HTTPS 记录:通过 DNS 记录直接声明支持 HTTP/3
  3. 客户端缓存:一旦发现服务器支持 HTTP/3,客户端会记住并在后续连接中直接使用

或使用在线工具检测:
– https://http3check.net/
– https://www.http2.pro/check

留下评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Index