WebSocket 协议介绍

前言

一.通用协议设计

参考链接

bash 复制代码
/*
+---------------------------------------------------------------+
| 魔数 2byte | 协议版本号 1byte | 序列化算法 1byte | 报文类型 1byte  |
+---------------------------------------------------------------+
| 状态 1byte |        保留字段 4byte     |      数据长度 4byte     | 
+---------------------------------------------------------------+
|                   数据内容 (长度不定)          | 校验字段 2byte |
+---------------------------------------------------------------+
*/

待补充

正文

二.WebSocket 协议

2.1 基础数据帧
术语 说明 大小
FIN 如果是 1,表示这是消息(message)的最后一个分片(fragment);如果是 0,表示不是是消息(message)的最后一个分片(fragment) 1bit
RSV1, RSV2, RSV3 一般情况下全为 0。当客户端、服务端协商采用 WebSocket 扩展时,这三个标志位可以非 0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用 WebSocket 扩展,连接出错 每个1 bit
Opcode 操作代码,Opcode 的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection) 4 bits
Mask 表示是否要对数据载荷进行掩码操作。 从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作。 如果服务端接收到的数据没有进行过掩码操作,服务端需要断开连接。 如果 Mask 是 1,那么在 Masking-key 中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧,Mask 都是 1。 1bit
Payload length 数据载荷的长度,单位是字节。假设数 Payload length === x,如果: x 为 0~126:数据的长度为 x 字节。 x 为 126:后续 2 个字节代表一个 16 位的无符号整数,该无符号整数的值为数据的长度。 x 为 127:后续 8 个字节代表一个 64 位的无符号整数(最高位为 0),该无符号整数的值为数据的长度。 此外,如果 payload length 占用了多个字节的话,payload length 的二进制表达采用网络序(big endian,重要的位在前)。 7 bits, 7+16 bits, 或者 7+64 bits
Masking-key 所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask 为 1,且携带了 4 字节的 Masking-key。如果 Mask 为 0,则没有 Masking-key。 备注:载荷数据的长度,不包括 mask key 的长度。 0 or 4 bytes
Payload data "负载数据"定义为"扩展数据"连接"应用数据"。 -Extension data: x byte "扩展数据"是 0 字节除非已经协商了一个扩展。任何扩展必须指定"扩展数据"的长度,或长度是如何计算的,以及扩展如何使用必须在打开阶段握手期间协商。如果存在,"扩展数据"包含在总负载长度中。 - Application data: y bytes 任意的"应用数据",占用"扩展数据"之后帧的剩余部分。"应用数据"的长度等于负载长度减去"扩展数据"长度。 (x+y) bytes

Opcode:

  • %x0 代表一个继续帧
  • %x1 代表一个文本帧
  • %x2 代表一个二进制帧
  • %x3-7 保留用于未来的非控制帧
  • %x8 代表连接关闭
  • %x9 代表 ping
  • %xA 代表 pong
  • %xB-F 保留用于未来的控制帧
2.2 数据帧另外一种表达方式
bash 复制代码
    ws-frame                = frame-fin           ; 1 bit in length
                              frame-rsv1          ; 1 bit in length
                              frame-rsv2          ; 1 bit in length
                              frame-rsv3          ; 1 bit in length
                              frame-opcode        ; 4 bits in length
                              frame-masked        ; 1 bit in length
                              frame-payload-length   ; either 7, 7+16,
                                                     ; or 7+64 bits in
                                                     ; length
                              [ frame-masking-key ]  ; 32 bits in length
                              frame-payload-data     ; n*8 bits in
                                                     ; length, where
                                                     ; n >= 0

    frame-fin               = %x0 ; more frames of this message follow
                            / %x1 ; final frame of this message
                                  ; 1 bit in length

    frame-rsv1              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise

    frame-rsv2              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise

    frame-rsv3              = %x0 / %x1
                              ; 1 bit in length, MUST be 0 unless
                              ; negotiated otherwise

    frame-opcode            = frame-opcode-non-control /
                              frame-opcode-control /
                              frame-opcode-cont

    frame-opcode-cont       = %x0 ; frame continuation

    frame-opcode-non-control= %x1 ; text frame
                            / %x2 ; binary frame
                            / %x3-7
                            ; 4 bits in length,
                            ; reserved for further non-control frames

    frame-opcode-control    = %x8 ; connection close
                            / %x9 ; ping
                            / %xA ; pong
                            / %xB-F ; reserved for further control
                                    ; frames
                                    ; 4 bits in length
                                    
    frame-masked            = %x0
                            ; frame is not masked, no frame-masking-key
                            / %x1
                            ; frame is masked, frame-masking-key present
                            ; 1 bit in length

    frame-payload-length    = ( %x00-7D )
                            / ( %x7E frame-payload-length-16 )
                            / ( %x7F frame-payload-length-63 )
                            ; 7, 7+16, or 7+64 bits in length,
                            ; respectively

    frame-payload-length-16 = %x0000-FFFF ; 16 bits in length

    frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
                            ; 64 bits in length

    frame-masking-key       = 4( %x00-FF )
                              ; present only if frame-masked is 1
                              ; 32 bits in length

    frame-payload-data      = (frame-masked-extension-data
                               frame-masked-application-data)
                            ; when frame-masked is 1
                              / (frame-unmasked-extension-data
                                frame-unmasked-application-data)
                            ; when frame-masked is 0

    frame-masked-extension-data     = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0

    frame-masked-application-data   = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0

    frame-unmasked-extension-data   = *( %x00-FF )
                            ; reserved for future extensibility
                            ; n*8 bits in length, where n >= 0

    frame-unmasked-application-data = *( %x00-FF )
                            ; n*8 bits in length, where n >= 0
2.3 WebSocket掩码的作用

WebSocket的掩码算法是一种数据加密方法,‌用于保护数据传输的安全性。‌这种算法通过异或运算对数据进行处理,‌以防止早期版本的协议中存在的代理缓存污染攻击等问题。‌具体来说,‌掩码算法的实现过程如下:‌

  1. 掩码的作用:‌掩码算法并不是为了防止数据泄密,‌而是为了防止代理缓存污染攻击等问题。‌它通过对数据进行异或运算,‌使得原始数据在传输过程中被改变,‌只有在接收端使用相同的掩码进行反向操作,‌才能还原出原始数据。‌

  2. 算法描述:‌对于每个需要发送的字节,‌它通过与掩码密钥进行异或运算来生成传输的数据。‌具体来说,‌对于原始数据中的每个字节original-octet-i,‌它首先计算j = i MOD 4来获取掩码密钥中的对应字节masking-key-octet-j,为mask key第j个字节。‌然后,‌将original-octet-i与masking-key-octet-j进行异或运算,‌得到的结果即为传输的数据

    即:j = i MOD 4

    transformed-octet-i = original-octet-i XOR masking-key-octet-j。‌

bash 复制代码
void umask(char *payload, int len, char *mask)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        payload[i] ^= mask[i % 4];
    }
}
  1. 示例:‌以客户端发送语音文件到服务端的场景为例,‌客户端首先发送txt消息文件名称,‌然后再发送bin消息二进制流数据。‌在这个过程中,‌客户端对需要发送的字符与掩码进行异或运算,‌生成用于网络传输的数据。‌例如,‌字符't'的ASCII值为116,‌与掩码14进行异或运算后,‌得到的结果用于传输。‌

待补充

2.4 分片(Fragmentation)
2.5 控制帧
2.5.1 Close
2.5.2 Ping
2.5.3 Pong
2.6 数据帧(payload)

三、私有协议示例

相关推荐
Petrichor-瑾2 小时前
HTTP和HTTPS的区别
网络·http·https
丢爸4 小时前
网络学习-eNSP配置NAT
linux·网络·学习
沐风ya4 小时前
NAT技术介绍+缺陷(内网穿透+工具),NAPT(介绍,替换过程,原理,NAT转换表)
linux·服务器·网络
天启代理ip5 小时前
HTTP隧道代理:互联网冲浪的隐形翅膀
服务器·网络·爬虫·网络协议·tcp/ip
6230_5 小时前
关于HTTP通讯流程知识点补充—常见状态码及常见请求方式
前端·javascript·网络·网络协议·学习·http·html
日记成书6 小时前
【无线通信发展史⑨】1791年路易吉·伽伐尼-关于动物电的研究与1800年亚历山大·伏打伯爵-电池:伏打电池
网络·人工智能·学习·职场和发展·信息与通信
achirandliu7 小时前
SOME/IP 通信协议详细介绍
网络·网络协议·tcp/ip·some/ip
我晕死哦7 小时前
Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法
python·网络协议·http·pycharm
长安初雪8 小时前
计算机网络 第三章: 数据链路层概述
网络·网络协议·计算机网络
铁蛋Q8 小时前
基于udp的socket网络编程
网络·网络协议·udp