http2

package
v0.1.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 8, 2024 License: MIT Imports: 10 Imported by: 1

README

HTTP/2 帧的基本结构

每个 HTTP/2 帧由两个部分组成:

帧头(Frame Header)

固定 9 字节,包含以下字段:

  • 长度(Length):24 位,表示帧负载的长度,不包括帧头本身。
  • 类型(Type):8 位,表示帧的类型。
  • 标志(Flags):8 位,表示帧的标志,用于指示特定的控制信息。
  • 流标识符(Stream Identifier):31 位,标识该帧所属的流,最高位保留为 0。

帧负载(Payload)

长度可变,内容根据帧类型不同而不同。

HTTP/2 的帧类型

HTTP/2 定义了以下 10 种帧类型,每种帧类型都有唯一的类型编号(Type):

  • DATA 帧(Type = 0x0)
  • HEADERS 帧(Type = 0x1)
  • PRIORITY 帧(Type = 0x2)
  • RST_STREAM 帧(Type = 0x3)
  • SETTINGS 帧(Type = 0x4)
  • PUSH_PROMISE 帧(Type = 0x5)
  • PING 帧(Type = 0x6)
  • GOAWAY 帧(Type = 0x7)
  • WINDOW_UPDATE 帧(Type = 0x8)
  • CONTINUATION 帧(Type = 0x9)

以下是对每种帧类型的详细介绍:

1. DATA 帧(Type = 0x0)

功能

用于传输 HTTP 消息的主体数据(例如请求体或响应体)。

结构
  • 帧头

    • 长度:可变
    • 类型:0x0
    • 标志:可能包含 END_STREAM(0x1)、PADDED(0x8)
    • 流标识符:所属的流 ID
  • 帧负载

    • 可选的 PADDED 字段(1 字节):表示填充字节的长度。
    • 数据:实际的有效负载数据。
    • 可选的填充字节:用于填充数据,长度由 PADDED 标志指定。
标志
  • END_STREAM (0x1):指示这是该流的最后一个帧。
  • PADDED (0x8):指示帧负载包含填充字节。

2. HEADERS 帧(Type = 0x1)

功能

用于传输 HTTP 请求或响应的头部信息。

结构
  • 帧头:

    • 长度:可变
    • 类型:0x1
    • 标志:可能包含 END_STREAM(0x1)、END_HEADERS(0x4)、PADDED(0x8)、PRIORITY(0x20)
    • 流标识符:所属的流 ID
  • 帧负载:

    • 可选的 PADDED 字段(1 字节):表示填充字节的长度。
    • 可选的 PRIORITY 字段(5 字节):包含依赖关系和权重。
      • 依赖的流 ID(31 位):指定当前流依赖的父流。
      • 权重(8 位):指定当前流的权重(1-256)。
    • 头部块:使用 HPACK 压缩的头部字段。
    • 可选的填充字节:用于填充数据,长度由 PADDED 标志指定。
标志
  • END_STREAM (0x1):指示这是该流的最后一个帧。
  • END_HEADERS (0x4):指示头部块已经完全传输。
  • PADDED (0x8):指示帧负载包含填充字节。
  • PRIORITY (0x20):指示帧负载包含优先级信息。

3. PRIORITY 帧(Type = 0x2)

功能

用于设置流的优先级和依赖关系。

结构
  • 帧头:

    • 长度:5 字节
    • 类型:0x2
    • 标志:无定义
    • 流标识符:所属的流 ID
  • 帧负载:

    • 依赖的流 ID(31 位):指定当前流依赖的父流。
    • 权重(8 位):指定当前流的权重(1-256)。
标志
  • 无定义,通常不使用标志。

4. RST_STREAM 帧(Type = 0x3)

功能

用于中止一个流,表明该流发生了错误或被取消。

结构
  • 帧头:

    • 长度:4 字节
    • 类型:0x3
    • 标志:无定义
    • 流标识符:所属的流 ID
  • 帧负载:

    • 错误码(32 位):指示中止原因(例如 NO_ERRORCANCELINTERNAL_ERROR 等)。
标志
  • 无定义,通常不使用标志。

5. SETTINGS 帧(Type = 0x4)

功能

用于配置和调整 HTTP/2 连接的参数,双方可以通过此帧来交换设置。

结构
  • 帧头:

    • 长度:可变(必须是 0 或 6 的倍数)
    • 类型:0x4
    • 标志:可能包含 ACK(0x1)
    • 流标识符:必须为 0(全连接设置)
  • 帧负载:

    • 设置项:每个设置项 6 字节,包含:
      • 设置标识符(16 位):表示设置的类型(例如 SETTINGS_HEADER_TABLE_SIZESETTINGS_ENABLE_PUSH 等)。
      • 设置值(32 位):对应设置项的值。
标志
  • ACK (0x1):确认接收到的 SETTINGS 帧,无需包含设置项。

6. PUSH_PROMISE 帧(Type = 0x5)

功能

服务器使用 PUSH_PROMISE 帧向客户端推送资源,提前发送可能需要的响应。

结构
  • 帧头:

    • 长度:可变
    • 类型:0x5
    • 标志:可能包含 END_HEADERS(0x4)、PADDED(0x8)
    • 流标识符:所属的流 ID(父流 ID)
  • 帧负载:

    • 可选的 PADDED 字段(1 字节):表示填充字节的长度。
    • 承诺的流 ID(31 位):被推送的流 ID。
    • 头部块:使用 HPACK 压缩的头部字段。
    • 可选的填充字节:用于填充数据,长度由 PADDED 标志指定。
标志
  • END_HEADERS (0x4):指示头部块已经完全传输。
  • PADDED (0x8):指示帧负载包含填充字节。

7. PING 帧(Type = 0x6)

功能

用于测量连接的往返时间(RTT)或确认连接的可用性。

结构
  • 帧头:

    • 长度:8 字节
    • 类型:0x6
    • 标志:可能包含 ACK(0x1)
    • 流标识符:必须为 0
  • 帧负载:

    • Opaque Data(8 字节):任意 8 字节数据,用于回显。
标志
  • ACK (0x1):确认收到的 PING 帧,回应相同的数据。

8. GOAWAY 帧(Type = 0x7)

功能

用于指示连接的终止,通知对方不再接受新的流。

结构
  • 帧头:

    • 长度:可变(至少 8 字节)
    • 类型:0x7
    • 标志:无定义
    • 流标识符:必须为 0
  • 帧负载:

    • 最后一个流 ID(31 位):指示发送方希望接收方不再接收的流 ID 之前的所有流均可继续处理。
    • 错误码(32 位):指示连接终止的原因(例如 NO_ERRORPROTOCOL_ERROR 等)。
    • 附加数据(可选):人类可读的错误信息,使用 UTF-8 编码。
标志
  • 无定义,通常不使用标志。

9. WINDOW_UPDATE 帧(Type = 0x8)

功能

用于调整流或连接的窗口大小,实现流量控制。

结构
  • 帧头:

    • 长度:4 字节
    • 类型:0x8
    • 标志:无定义
    • 流标识符:所属的流 ID(0 表示连接级别窗口)
  • 帧负载:

    • 窗口增量(31 位):表示窗口大小增加的字节数(必须大于 0)。
标志
  • 无定义,通常不使用标志。

10. CONTINUATION 帧(Type = 0x9)

功能

用于传输被分割的头部块,当 HEADERS 或 PUSH_PROMISE 帧的头部块过长时使用。

结构
  • 帧头:

    • 长度:可变
    • 类型:0x9
    • 标志:可能包含 END_HEADERS(0x4)、PADDED(0x8)
    • 流标识符:所属的流 ID
  • 帧负载:

    • 头部块:使用 HPACK 压缩的头部字段的后续部分。
    • 可选的填充字节(仅在 PADDED 标志下使用):用于填充数据,长度由 PADDED 标志指定。
标志
  • END_HEADERS (0x4):指示头部块已经完全传输。
  • PADDED (0x8):指示帧负载包含填充字节。

错误码

数据映射

错误码名称与其对应的 32 位无符号整数 之间存在明确的映射关系。每个错误码名称对应一个唯一的数值,这些数值在协议规范中被预定义。

标准错误码列表

根据 RFC 7540 规范,HTTP/2 定义了以下标准错误码:

错误码名称 数值(十六进制) 数值(十进制) 描述
NO_ERROR 0x0 0 正常关闭,无错误发生。
PROTOCOL_ERROR 0x1 1 一般协议错误,协议未被正确遵循。
INTERNAL_ERROR 0x2 2 内部错误,服务器遇到意外情况。
FLOW_CONTROL_ERROR 0x3 3 流量控制错误,流量控制机制被违反。
SETTINGS_TIMEOUT 0x4 4 设置超时,未能在规定时间内完成设置交换。
STREAM_CLOSED 0x5 5 流已关闭,尝试操作一个已关闭的流。
FRAME_SIZE_ERROR 0x6 6 帧大小错误,接收到的帧大小不符合协议要求。
REFUSED_STREAM 0x7 7 拒绝流,请求被服务器拒绝。
CANCEL 0x8 8 请求被取消,客户端或服务器主动取消请求。
COMPRESSION_ERROR 0x9 9 压缩错误,头部压缩(HPACK)出现问题。
CONNECT_ERROR 0xa 10 连接错误,CONNECT 方法失败。
ENHANCE_YOUR_CALM 0xb 11 服务器认为客户端发送请求过于频繁,需要冷静。
INADEQUATE_SECURITY 0xc 12 安全性不足,使用的加密套件不被接受。
HTTP_1_1_REQUIRED 0xd 13 需要使用 HTTP/1.1 协议,HTTP/2 不支持的特性。

错误码的扩展与自定义

虽然上述列出了标准的 HTTP/2 错误码,但协议允许实现者定义 自定义错误码。自定义错误码需遵循以下规则:

  1. 范围限制:自定义错误码的数值应大于 0xd(13),避免与标准错误码冲突。
  2. 分配管理:通常由组织或开发者自行管理,确保错误码的唯一性和一致性。
  3. 文档记录:自定义错误码应在相关文档中详细记录其含义和使用场景,方便双方理解和调试。

错误码的使用示例

在 RST_STREAM 帧中使用错误码

当服务器决定终止某个流时,会发送一个 RST_STREAM 帧,并在帧负载中包含相应的错误码。例如:

RST_STREAM Frame:
- Frame Header:
  - Length: 4
  - Type: 0x3
  - Flags: 0x0
  - Stream Identifier: 1
- Frame Payload:
  - Error Code: 0x1 (PROTOCOL_ERROR)
在 GOAWAY 帧中使用错误码

当服务器决定终止整个连接时,会发送一个 GOAWAY 帧,并在帧负载中包含最后一个有效的流标识符和错误码。例如:

GOAWAY Frame:
- Frame Header:
  - Length: 8
  - Type: 0x7
  - Flags: 0x0
  - Stream Identifier: 0
- Frame Payload:
  - Last Stream ID: 100
  - Error Code: 0x2 (INTERNAL_ERROR)

总结

HTTP/2 的错误码机制通过 32 位无符号整数 的二进制格式高效传输错误信息,帮助通信双方快速定位和处理问题。标准错误码涵盖了从正常关闭到各种协议和内部错误的广泛场景,同时也支持自定义错误码以满足特定需求。理解和正确使用这些错误码,对于开发和维护稳定、高效的 HTTP/2 应用至关重要。

各帧类型的使用场景与注意事项

数据帧与头部帧

  • DATA 和 HEADERS 帧是传输实际 HTTP 数据的主要载体。HEADERS 帧用于发送头部信息,而 DATA 帧用于发送主体内容。
  • CONTINUATION 帧用于处理过长的头部块,确保头部信息可以被分割成多个帧传输。

流优先级与控制

  • PRIORITY 帧允许客户端和服务器设定流的优先级,优化资源分配和响应时间。
  • WINDOW_UPDATE 帧实现流量控制,防止发送方过快地发送数据,导致接收方处理不过来。

连接管理

  • SETTINGS 帧用于初始化和更新连接的配置参数,如最大并发流数、初始窗口大小等。
  • PING 帧用于检测连接的活跃性和测量延迟。
  • GOAWAY 帧用于优雅地终止连接,通知对方不再接受新的流。

错误处理

  • RST_STREAM 帧用于中止特定流,通知对方发生了错误或取消请求。
  • GOAWAY 帧用于中止整个连接,适用于严重错误或维护需要。

服务推送

  • PUSH_PROMISE 帧允许服务器向客户端主动推送资源,减少延迟和提高性能。

总结

HTTP/2 的帧机制极大地提升了网络传输的效率和灵活性。 通过多种帧类型的协同工作,HTTP/2 实现了多路复用、头部压缩、流量控制和优先级管理等先进特性。 这些帧类型的详细理解和正确使用,对于开发高性能、可扩展的网络应用至关重要。

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeGrpcFrame

func DecodeGrpcFrame(data []byte, message proto.Message) error

func DecodeGrpcFrameWithDecompress

func DecodeGrpcFrameWithDecompress(data []byte, compressionAlgo string, message proto.Message) error

func DecodeGrpcPayload

func DecodeGrpcPayload(data []byte) ([]byte, error)

func EncodeGrpcFrame

func EncodeGrpcFrame(message proto.Message) ([]byte, error)

func EncodeGrpcPayload

func EncodeGrpcPayload(payload []byte) []byte

func ReadFrames

func ReadFrames(rw io.ReadWriter, response proto.Message) error

func WriteDataFrame

func WriteDataFrame(w io.Writer, streamID uint32, body []byte) error

func WriteHeadersFrame

func WriteHeadersFrame(w io.Writer, streamID uint32, headers []hpack.HeaderField) error

func WritePingFrame

func WritePingFrame(w io.Writer, payload []byte) error

func WriteSettingsFrame

func WriteSettingsFrame(w io.Writer, flags byte, payload []byte) error

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL