websocket协议解读

websocket协议

RFC 6455

消息结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 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 1bit

消息的最后一帧 (第一帧也可以是最后一帧)

RSV1,RSV2,RSV3 每个1bit

必须为0,除非双方协商定义了非零值的扩展,如果非零且未协商定义,则收到的终端必须断开WebSocket连接

Opcode 4bits

定义了交互的携带数据, 如果收到位置的opcode,收到的终端必须断开WebSocket连接

  • %x0 附加数据帧
  • %x1 文本数据帧
  • %x2 二进制数据帧
  • %x3-7 保留的opcode,用于非控制帧
  • %x8 连接关闭
  • %x9 ping
  • %xA pong
  • %xB-F 保留的opcode,用于控制帧

Mask 1bit

用于标识Playload Data是否经过掩码处理。如果是1,Masking-key域的数据就是掩码密钥,用于解码Payload Data。客户端发出的数据帧需要进行掩码处理,所以要设置为1。

Payload length 7bits,7+16bits,7+64bits

PayloadData的长度解释 (以字节为单位)。

  • 如果其值在0-125,则是payload的真实长度。
  • 如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
  • 如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
    长度表示遵循一个原则,用最少的字节表示长度(我理解是尽量减少不必要的传输)。举例说,payload真实长度是124,在0-125之间,必须用前7位表示;不允许长度1是126或127,然后长度2是124,这样违反原则。
    Payload长度是ExtensionData长度与ApplicationData长度之和。ExtensionData长度可能是0,这种情况下,Payload长度即是ApplicationData长度。

Masking-key 0 or 4 bytes

WebSocket协议规定数据通过帧序列传输,特点如下:

  • 客户端必须对其发送到服务器的所有帧进行掩码处理(32位的值)。
  • 服务器一旦收到无掩码帧,将关闭连接。服务器可能发送一个状态码是1002(表示协议错误)的Close帧。
  • 服务器发送客户端的数据帧不做掩码处理,一旦客户端发现经过掩码处理的帧,将关闭连接。客户端可能使用状态码1002。

Payload data (x+y)bytes

Payload data 被定义为扩展数据(Extension Data)加上应用数据(Application Data)

Extension Data x bytes

如果客户端与服务端之间没有特殊约定,那么扩展数据的长度始终为0,任何的扩展都必须指定扩展数据的长度,或者长度的计算方式,以及在握手时如何确定正确的握手方式。如果存在扩展数据,则扩展数据就会包括在负载数据的长度之内

Application Data y bytes

任意的应用数据,放在扩展数据之后,应用数据的长度=负载数据的长度-扩展数据的长度。

消息分片

分片目的是发送长度未知的消息。如果不分片发送,即一帧,就需要缓存整个消息,计算其长度,构建frame并发送;使用分片的话,可使用一个大小合适的buffer,用消息内容填充buffer,填满即发送出去。
分片规则:

  1. 一个未分片的消息只有一帧(FIN为1,opcode非0)
  2. 一个分片的消息由起始帧(FIN为0,opcode非0),若干(0个或多个)帧(FIN为0,opcode为0),结束帧(FIN为1,opcode为0)。
  3. 控制帧可以出现在分片消息中间,但控制帧本身不允许分片。
  4. 分片消息必须按次序逐帧发送。
  5. 如果未协商扩展的情况下,两个分片消息的帧之间不允许交错。
  6. 能够处理存在于分片消息帧之间的控制帧
  7. 发送端为非控制消息构建长度任意的分片
  8. client和server兼容接收分片消息与非分片消息
  9. 控制帧不允许分片,中间媒介不允许改变分片结构(即为控制帧分片)
  10. 如果使用保留位,中间媒介不知道其值表示的含义,那么中间媒介不允许改变消息的分片结构
  11. 如果协商扩展,中间媒介不知道,那么中间媒介不允许改变消息的分片结构,同样地,如果中间媒介不了解一个连接的握手信息,也不允许改变该连接的消息的分片结构
  12. 由于上述规则,一个消息的所有分片是同一数据类型(由第一个分片的opcode定义)的数据。因为控制帧不允许分片,所以一个消息的所有分片的数据类型是文本、二进制、opcode保留类型中的一种。
    需要注意的是,如果控制帧不允许夹杂在一个消息的分片之间,延迟会较大,比如说当前正在传输一个较大的消息,此时的ping必须等待消息传输完成,才能发送出去,会导致较大的延迟。为了避
    免类似问题,需要允许控制帧夹杂在消息分片之间。

控制帧

用于控制WebSocket协议的通信状态,控制帧可以出现在分片消息中,但是其长度必须小于等于125,因为控制帧不允许分片。

  • 0x8 close
  • 0x9 ping
  • 0xA pong
  • 0xB-F 保留

数据帧

  • 0x1 text 文本数据
  • 0x2 binary 二进制数据
您的支持将鼓励我继续创作!