当前位置: 首页 > news >正文

WebSocket 协议介绍

前言

一.通用协议设计

参考链接

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

待补充

正文

二.WebSocket 协议

2.1 基础数据帧

WebSocket数据帧

术语说明大小
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 数据帧另外一种表达方式
    ws-frame                = frame-fin           ; 1 bit in lengthframe-rsv1          ; 1 bit in lengthframe-rsv2          ; 1 bit in lengthframe-rsv3          ; 1 bit in lengthframe-opcode        ; 4 bits in lengthframe-masked        ; 1 bit in lengthframe-payload-length   ; either 7, 7+16,; or 7+64 bits in; length[ frame-masking-key ]  ; 32 bits in lengthframe-payload-data     ; n*8 bits in; length, where; n >= 0frame-fin               = %x0 ; more frames of this message follow/ %x1 ; final frame of this message; 1 bit in lengthframe-rsv1              = %x0 / %x1; 1 bit in length, MUST be 0 unless; negotiated otherwiseframe-rsv2              = %x0 / %x1; 1 bit in length, MUST be 0 unless; negotiated otherwiseframe-rsv3              = %x0 / %x1; 1 bit in length, MUST be 0 unless; negotiated otherwiseframe-opcode            = frame-opcode-non-control /frame-opcode-control /frame-opcode-contframe-opcode-cont       = %x0 ; frame continuationframe-opcode-non-control= %x1 ; text frame/ %x2 ; binary frame/ %x3-7; 4 bits in length,; reserved for further non-control framesframe-opcode-control    = %x8 ; connection close/ %x9 ; ping/ %xA ; pong/ %xB-F ; reserved for further control; frames; 4 bits in lengthframe-masked            = %x0; frame is not masked, no frame-masking-key/ %x1; frame is masked, frame-masking-key present; 1 bit in lengthframe-payload-length    = ( %x00-7D )/ ( %x7E frame-payload-length-16 )/ ( %x7F frame-payload-length-63 ); 7, 7+16, or 7+64 bits in length,; respectivelyframe-payload-length-16 = %x0000-FFFF ; 16 bits in lengthframe-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF; 64 bits in lengthframe-masking-key       = 4( %x00-FF ); present only if frame-masked is 1; 32 bits in lengthframe-payload-data      = (frame-masked-extension-dataframe-masked-application-data); when frame-masked is 1/ (frame-unmasked-extension-dataframe-unmasked-application-data); when frame-masked is 0frame-masked-extension-data     = *( %x00-FF ); reserved for future extensibility; n*8 bits in length, where n >= 0frame-masked-application-data   = *( %x00-FF ); n*8 bits in length, where n >= 0frame-unmasked-extension-data   = *( %x00-FF ); reserved for future extensibility; n*8 bits in length, where n >= 0frame-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。‌

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)

三、私有协议示例

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 谷粒商城实战笔记-103~104-全文检索-ElasticSearch-Docker安装ES和Kibana
  • 什么是嵌入式
  • uniapp中实现语音识别(app+小程序)
  • C++解决:早餐组合
  • 抽象代数精解【4】
  • Web开发:用C#的逻辑理解VUE语法(VUE + Webapi小白开发笔记)
  • k8s安装ingress-nginx
  • [H贪心] lc100376. 新增道路查询后的最短距离 II(贪心+读题+代码实现+周赛409_3)
  • web3 solana
  • 机器学习练手(六):机器学习算法实践实战
  • 【深度学习】【框架】【基本结构】transformer
  • Python如何将Category类的数组categoryList,导出成JSON格式
  • Action部署在线上写文章
  • C#根据反射操作对象
  • 操作系统篇--八股文学习第十二天| 什么是死锁,如何避免死锁?,介绍一下几种典型的锁,讲一讲你理解的虚拟内存
  • 「面试题」如何实现一个圣杯布局?
  • Django 博客开发教程 16 - 统计文章阅读量
  • Docker容器管理
  • exports和module.exports
  • Java|序列化异常StreamCorruptedException的解决方法
  • js对象的深浅拷贝
  • LintCode 31. partitionArray 数组划分
  • Linux Process Manage
  • Object.assign方法不能实现深复制
  • python 装饰器(一)
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 闭包--闭包之tab栏切换(四)
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 关于Flux,Vuex,Redux的思考
  • 猴子数据域名防封接口降低小说被封的风险
  • 基于遗传算法的优化问题求解
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 入手阿里云新服务器的部署NODE
  • 数组的操作
  • 小而合理的前端理论:rscss和rsjs
  • 延迟脚本的方式
  • 自制字幕遮挡器
  • 《码出高效》学习笔记与书中错误记录
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • #《AI中文版》V3 第 1 章 概述
  • #laravel 通过手动安装依赖PHPExcel#
  • #pragam once 和 #ifndef 预编译头
  • #每天一道面试题# 什么是MySQL的回表查询
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (26)4.7 字符函数和字符串函数
  • (C++)八皇后问题
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (笔试题)合法字符串
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (三)elasticsearch 源码之启动流程分析
  • (十二)Flink Table API
  • (四)模仿学习-完成后台管理页面查询