WebSocket 协议 5~10 节

WebSocket 协议 5~10 节

第 1~4 节在 WebSocket 协议 1~4 节;

5. 使用帧去组织数据

5.1 概览

在 WebSocket 协议中,数据的传输使用一连串的帧。为了使得中间件不至于混淆(比如代理服务器)以及为了第 10.3 节将讨论安全原因,客户端必须将要发送到服务端的帧进行掩码,掩码将在第 5.3 节详细讨论。(注意,不管 WebSocket 有没有运行在 TLS 之上,都必须有掩码操作)服务端一旦接收到没有进行掩码的帧的话,必须关闭连接。这种情况下,服务端可以发送一个关闭帧,包含一个状态码 1002(协议错误 protocol error),相关定义在 Section 7.4.1。服务端不必对发送到客户端的任何帧进行掩码。如果客户端接收到了服务端的掩码后的帧,客户端必须关闭连接。在这个情况下,客户端可以向服务器发送关闭帧,包含状态码 1002(协议错误 protocol error),相关定义在 Section 7.4.1。(这些规则可能在将来技术说明中没有严格要求)

基础帧协议通过操作码(opcode)定义了一个帧类型,一个有效负荷长度,以及特定的位置存放 “扩展数据 Extension data” 和 “应用数据 Application data”,扩展数据和应用数据合起来定义了 “有效负荷数据 Payload data”。某些数位和操作码是保留的,为了将来的使用。

在客户端和服务端完成了握手之后,以及任意一端发送的关闭帧(在第 5.5.1 节介绍)之前,客户端可以和服务端都可以在任何时间发送数据帧。

基础帧协议

这一节中将使用 ABNF 详细定义数据传输的格式。(注意,和这文档中的其他 ABNF 不同,这一节中 ABNF 操作的是一组数位。每一组数位的长度将以注释的形式存在。当数据在网络中传输时,最高有效位是在 ABNF 的最左边(大端序))。下面的文本图像可以给出关于帧的一个高层概览。如果下面的文本插图和后的 ABNF 描述发送冲突时,以插图为准。

  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)

    标记这个帧是不是消息中的最后一帧。第一个帧也可以是最后一帧。

  • RSV1,RSV2,RSV3: 各 1 个数位

    必须是 0,除非有扩展赋予了这些数位非 0 值的意义。如果接收到了一个非 0 的值并且没有扩展赋予这些非 0 值的意义,那么接收端需要标记连接为失败。

  • 操作码:4 个数位
    定义了如何解释 “有效负荷数据 Payload data”。如果接收到一个未知的操作码,接收端必须标记 WebSocket 为失败。定义了如下的操作码:

    • %x0 表示这是一个继续帧(continuation frame)
    • %x1 表示这是一个文本帧 (text frame)
    • %x2 表示这是一个二进制帧 (binary frame)
    • %x3-7 为将来的非控制帧(non-control frame)而保留的
    • %x8 表示这是一个连接关闭帧 (connection close)
    • %x9 表示这是一个 ping 帧
    • %xA 表示这是一个 pong 帧
    • xB-F 为将来的控制帧(control frame)而保留的
  • 掩码标识 Mask:1 个数位

    定义了 “有效负荷数据” 是否是被掩码的。如果被设置为 1,那么在 masking-key 部分将有一个掩码钥匙(masking key),并且使用这个掩码钥匙去将 “有效负荷数据” 进行反掩码操作(第 5.3 节描述)。所有的由客户端发往服务端的帧此数位都被设置成 1。

  • 有效负荷长度(Payload length): 7、7+16 或者 7+64 数位

    表示了 “有效负荷数据 Payload data” 的长度,以字节为单位:如果是 0-125,那么就直接表示了负荷长度。如果是 126,那么接下来的两个字节表示的 16 位无符号整型数则是负荷长度。如果是 127,则接下来的 8 个字节表示的 64 位无符号整型数则是负荷长度。表示长度的数值的字节是按网络字节序(network byte order 即大端序)表示的。注意在所有情况下,必须使用最小的负荷长度,比如,对于一个 124 字节长度的字符串,长度不可以编码成 126,0,124。负荷长度是 “扩展数据 Extension data” 长度 + “应用数据Application data” 长度 。“扩展数据” 的长度可以是 0,那么此时 “应用数据” 的长度就是负荷长度。

  • 掩码钥匙 Masking key:0 或者 4 个数位

    所有由客户端发往服务端的帧中的内容都必须使用一个 32 位的值进行掩码。这个字段有值的时候(占 4 个数位)仅当掩码标识位设置成了 1,如果掩码标识位设置为 0,则此字段没有值(占 0 个数位)。对于进一步掩码操作,见第 5.3 节。

    1 2 3 4 5 6 7 
    下一页