• websocket报文格式及掩码处理方式


    1、数据帧格式概览

    下面给出了WebSocket数据帧的统一格式。熟悉TCP/IP协议的同学对这样的图应该不陌生。

    1. 从左到右,单位是比特。比如FIN、RSV1各占据1比特,opcode占据4比特。
    2. 内容包括了标识、操作代码、掩码、数据、数据长度等。(下一小节会展开)
     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 ...                |
     +---------------------------------------------------------------+
    
    2、数据帧格式详解

    针对前面的格式概览图,这里逐个字段进行讲解,如有不清楚之处,可参考协议规范,或留言交流。

    FIN:1个比特。

    如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)。

    RSV1, RSV2, RSV3:各占1个比特。

    一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用WebSocket扩展,连接出错。

    Opcode: 4个比特。

    操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection)。可选的操作代码如下:

    %x0:表示一个延续帧。当Opcode为0时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片。
    %x1:表示这是一个文本帧(frame)
    %x2:表示这是一个二进制帧(frame)
    %x3-7:保留的操作代码,用于后续定义的非控制帧。
    %x8:表示连接断开。
    %x9:表示这是一个ping操作。
    %xA:表示这是一个pong操作。
    %xB-F:保留的操作代码,用于后续定义的控制帧。
    
    Mask: 1个比特。

    表示是否要对数据载荷进行掩码操作。从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作。

    如果服务端接收到的数据没有进行过掩码操作,服务端需要断开连接。

    如果Mask是1,那么在Masking-key中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧,Mask都是1。
    掩码的算法、用途在下一小节讲解。

    Payload length:

    数据载荷的长度,单位是字节。为7位,或7+16位,或1+64位。

    假设数Payload length === x,如果

    x为0~126:数据的长度为x字节。
    x为126:后续2个字节代表一个16位的无符号整数,该无符号整数的值为数据的长度。
    x为127:后续8个字节代表一个64位的无符号整数(最高位为0),该无符号整数的值为数据的长度。
    此外,如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)。

    Masking-key:0或4字节(32位)

    所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。

    备注:载荷数据的长度,不包括mask key的长度。

    Payload data:(x+y) 字节

    载荷数据:包括了扩展数据、应用数据。其中,扩展数据x字节,应用数据y字节。

    扩展数据:如果没有协商使用扩展的话,扩展数据数据为0字节。所有的扩展都必须声明扩展数据的长度,或者可以如何计算出扩展数据的长度。此外,扩展如何使用必须在握手阶段就协商好。如果扩展数据存在,那么载荷数据长度必须将扩展数据的长度包含在内。

    应用数据:任意的应用数据,在扩展数据之后(如果存在扩展数据),占据了数据帧剩余的位置。载荷数据长度 减去 扩展数据长度,就得到应用数据的长度。

    3、掩码算法

    掩码键(Masking-key)是由客户端挑选出来的32位的随机数。掩码操作不会影响数据载荷的长度。掩码、反掩码操作都采用如下算法:

    首先,假设:

    original-octet-i:为原始数据的第i字节。
    transformed-octet-i:为转换后的数据的第i字节。
    j:为i mod 4的结果。
    masking-key-octet-j:为mask key第j字节。
    

    算法描述为:
    original-octet-imasking-key-octet-j异或后,得到 transformed-octet-i

    j = i MOD 4
    transformed-octet-i = original-octet-i XOR masking-key-octet-j
    
    4、掩码样例

    场景:
    客户端:发送语音文件到服务端,先发送txt消息文件名称"tts";再读物文件,发送bin消息二进制流数据(多帧发送)。

    服务端:先接收txt消息,需要接收的文件名称并创建打开;再接收bin消息语音流消息,并写入文件;当接收到最后一帧二进制后,关闭打开的文件。

    txt消息生成的 掩码KEY:

    the key is 14,51,172,208.
    

    客服端处理消息:“tts” =》122,71,-33

    1. 客户端生成原始4位掩码
    2. 将需要发送字符与掩码异或运算,获取计算后的值,用于网络传输。
      116(t)与掩码14异或处理,得到异或值:122
      116(t)与掩码51异或处理,得到异或值:71
      115(s)与掩码172异或处理,得到异或值:223
    3. 生成待发送消息:121,71,223

    服务端处理消息:122,71,223 =》 “tts”

    1. 获取客户端发送的4位掩码和数据消息
    2. 将收到的字符消息与掩码异或运算,获取源字符值
      122与掩码(14)异或处理,得到原字符值:116(t)
      71与掩码(51)异或处理,得到原字符值:116(t)
      233与掩码(172)异或处理,得到原字符值:115(s)
    3. 解码获取文件名:116,116,115;及字符:tts
  • 相关阅读:
    构建单页面应用
    chrome进入控制台时自动进入断点模式的解决方法
    git安装--linux下的安装
    express响应前端ajax请求
    nodejs链接mongodb数据库
    Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍
    Nginx中如何限制某个IP同一时间段的访问次数
    nodejs && apidoc
    apidoc
    android sdk
  • 原文地址:https://www.cnblogs.com/laohaozi/p/12537571.html
Copyright © 2020-2023  润新知