1.2 二进制帧格式

Format

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
+---------------------------------------------------------------+
|                        Session Id (32)                        |
+---------------------------------------------------------------+
|                        timestamp ...                          |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                    ... timestamp (64)                         |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|S|P|F| RSV |S|F|  RSV  |OPCODE |          Payload len          |
|T|A|R| (3) |L|I|  (4)  | (4)   |             (16)              |
|R|C|A|     |O|N|       |       |                               |
|E|K|G|     |W| |       |       |                               |
+-+-+-+-----+-+-+-------+-------+-------------------------------+
|                        Stream Id (32)                         |
|                       (if STRE set to 1)                      |
+---------------------------------------------------------------+
|                        Packet Id (32)                         |
|                       (if PACK set to 1)                      |
+---------------------------------------------------------------+
|                        Fragment Id (32)                       |
|                       (if FRAG set to 1)                      |
+---------------------------------------------------------------+
:                        Payload Data ...                       :
+---------------------------------------------------------------+

Fields

  • Session Id: 4 bytes

    唯一标识一个 session,由连接双方在握手阶段共同生成。客户端生成高 16 位,服务端生成低 16 位。客户端与服务端生成时分别采用无符号 16 位随机整数。

  • timestamp: 64 bits

    发送当前帧时的时间戳,精确到毫秒。接收方收到该帧时,可知晓该帧于什么时间发出。由于客户端与服务端位于拓扑结构异常复杂的互联网环境中,所以双方的时间几乎肯定是不同步的,甚至误差较大,所以该时间戳只是用于粗略估计。

  • STRE: 1 bit

    Stream 标记,如果设置表明当前帧通过 Stream 发送或接收,头部中有 Stream Id 字段标识所属 Stream

  • PACK: 1 bit

    Packet 标记,如果设置表明当前帧是一个数据包,头部中有 Packet Id 字段标识所属 Packet

  • FRAG: 1 bit

    Fragment 标记,如果设置表明当前帧是 Packet 中的一个分片,头部中有 Fragment Id 字段标识所属 Fragment

  • RSV: 3 bits

    保留位,扩展协议时使用

  • SLOW: 1 bit

    降速标记,接收数据包时,如果发送端发送速度过快,接收端接收缓存已满,在发送 ack 帧给发送端时可设置该标记,通知发送端降低发送速度。

  • FIN: 1 bit

    最后一个分片标记,一旦 Packet 数据长度超过 MTU 就需要分片,在发送最后一个分片时,需要设置该标记,使得接收端得知分片数量并确定是否已接收全部分片。

  • RSV: 4 bits

    保留位,扩展协议时使用

  • OPCODE: 4 bits

    定义帧类型,不同类型的帧完成不同的功能,对所负载数据(Payload)的解释也不同。如果收到了未定义的 opcode,则该帧必须被丢弃。

    • %x0 (data) 二进制数据帧,携带二进制数据

    • %x1-3 保留的非控制帧

    • %x4 (ack) 确认数据已达帧

    • %x5 (ping) 心跳检测帧

    • %x6 (pong) 心跳应答帧

    • %x7 (openstream) 请求创建 Stream 帧

    • %x8 (streamopen) 创建 Stream 应答帧

    • %x9 (closestream) 请求关闭 Stream 帧

    • %xA (shakehand) 请求连接创建 Session 帧

    • %xB (handshake) 创建 Session 应答帧

    • %xC (goaway) 请求关闭 Session 帧

    • %xD-F 保留控制帧

  • Payload length: 2 bytes

    2 字节无符号整数,当前帧负载数据(Payload)长度,应不超过 MTU 值。

  • Stream Id: 0 or 4 bytes

    4 字节无符号整数,当设置 STRE 标记时,需要写入该字段标识当前数据包所属 Stream,如果未设置 STRE 标记,则该字段缺席。

  • Packet Id: 0 or 4 bytes

    4 字节无符号整数,当设置 PACK 标记时,需要写入该字段标识当前数据包所属 Packet,如果未设置 PACK 标记,则该字段缺席。

  • Fragment Id: 0 or 4 bytes

    4 字节无符号整数,当设置 FRAG 标记时,需要写入该字段标识当前数据包分片所属 Fragment,以及 Fragment 在所属 Packet 中的序号,如果未设置 FRAG 标记,则该字段缺席。

  • Payload Data: [Payload length] bytes

    负载数据,数据长度由 payload length 字段定义