乐闻世界logo
搜索文章和话题

WebSocket的消息帧格式是怎样的?

2月18日 18:56

WebSocket协议使用帧(Frame)来传输数据,每个帧都有特定的格式和用途。

帧的基本结构

WebSocket帧由多个字段组成,格式如下:

shell
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+

字段详解

FIN (1 bit)

  • 标识是否为消息的最后一个分片
  • 1:表示这是最后一个分片
  • 0:表示后面还有分片

RSV1, RSV2, RSV3 (各1 bit)

  • 保留位,必须为0
  • 除非扩展协商了非零值

Opcode (4 bits)

定义帧的操作类型:

Opcode含义
0x0继续帧
0x1文本帧
0x2二进制帧
0x8关闭连接
0x9Ping
0xAPong
0xB-F保留用于扩展

MASK (1 bit)

  • 标识Payload Data是否使用掩码
  • 客户端发送的帧必须为1
  • 服务器发送的帧必须为0

Payload Length (7 bits, 7+16 bits, or 7+64 bits)

负载长度,三种编码方式:

  • 0-125:直接表示长度
  • 126:后续2字节表示长度(16位无符号整数)
  • 127:后续8字节表示长度(64位无符号整数)

Masking-key (32 bits)

  • 当MASK=1时存在
  • 用于解码Payload Data
  • 客户端必须使用随机掩码

Payload Data

实际传输的数据,如果使用掩码,需要解码

掩码算法

javascript
function unmask(maskedData, maskingKey) { const result = new Uint8Array(maskedData.length); for (let i = 0; i < maskedData.length; i++) { result[i] = maskedData[i] ^ maskingKey[i % 4]; } return result; }

消息分片

大消息可以分成多个帧传输:

  1. 第一个帧:FIN=0,Opcode!=0
  2. 中间帧:FIN=0,Opcode=0
  3. 最后一个帧:FIN=1,Opcode=0

关闭帧

关闭连接时发送关闭帧:

  • Opcode=0x8
  • Payload包含状态码(2字节)和可选的关闭原因
标签:WebSocket