5. 使用帧去组织数据5.1 概览在 WebSocket 协议中,数据的传输使用一连串的帧。为了使得中间件不至于混淆(比如代理服务器)以及为了第 10.3 节将讨论安全原因,客户端必须将要发送到服务端的帧进行掩码,掩码将在第 5.3 节详细讨论。(注意,不管 WebSocket 有没有运行在 TLS 之上,都必须有掩码操作)服务端一旦接收到没有进行掩码的帧的话,必须关闭连接。这种情况下,服务端可以发送一个关闭帧,包含一个状态码 1002(协议错误 protocol error),相关定义在 。服务端不必对发送到客户端的任何帧进行掩码。如果客户端接收到了服务端的掩码后的帧,客户端必须关闭连接。在这个情况下,客户端可以向服务器发送关闭帧,包含状态码 1002(协议错误 protocol error),相关定义在 。(这些规则可能在将来技术说明中没有严格要求)
基础帧协议通过操作码(opcode)定义了一个帧类型,一个有效负荷长度,以及特定的位置存放 “扩展数据 Extension data” 和 “应用数据 Application data”,扩展数据和应用数据合起来定义了 “有效负荷数据 Payload data”。某些数位和操作码是保留的,为了将来的使用。
在客户端和服务端完成了握手之后,以及任意一端发送的关闭帧(在第 5.5.1 节介绍)之前,客户端可以和服务端都可以在任何时间发送数据帧。
基础帧协议这一节中将使用 ABNF 详细定义数据传输的格式。(注意,和这文档中的其他 ABNF 不同,这一节中 ABNF 操作的是一组数位。每一组数位的长度将以注释的形式存在。当数据在网络中传输时,最高有效位是在 ABNF 的最左边(大端序))。下面的文本图像可以给出关于帧的一个高层概览。如果下面的文本插图和后的 ABNF 描述发送冲突时,以插图为准。
View Code
- 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 节。
- 有效负荷数据 Payload data:(x+y) 字节 byte
“有效负荷数据” 的定义是 “扩展数据” 联合 “应用数据”。
- 扩展数据 Extension data: x 字节
“扩展数据是” 0 个字节的,除非协商了一个扩展。任何的扩展都必须提供 “扩展数据” 的长度或者该长度应该如何计算,以及在握手阶段如何使用 “扩展数据” 进行扩展协商。如果 “扩展数据” 存在,那么它的长度被包含在了负荷长度中。
- 应用数据 Application data: y字节
可以是任意的 “应用数据”,它在一个帧的范围内紧接着 “扩展数据”。“应用数据” 的长度等于负荷长度减去 “扩展数据” 的长度
基础帧协议通过接下来的 ABNF 来定义其形式。一个重要的注意点就是下面的 ABNF 表示的是二进制数据,而不是其表面上的字符串。比如, %x0 和 %x1 各表示一个数位,数位上的值为 0 和 1,而不是表示的字符 “0” 和 “1” 的 ASCII 编码。 没有定义 ABNF 的字符编码。在这里,ABNF 被特定了使用的是二进制编码,这里二进制编码的意思就是每一个值都被编码成具有特定数量的数位,具体的数量因不同的字段而异。 |