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

前端websocket更新列表数据_详解前端websocket服务器之数据传输协议

前言

上一篇文章我们初步搭建了一个websocket服务器,但是还不能发送和接收数据,这篇文章我们聊一聊它是如何收发数据的。websocket支持文本和二进制的传输,内部是如何接收和发送数据的对使用者来说是不可见的,虽然这不影响使用,但是为了更加深入了解websocket的原理,我们还是有必要一探究竟!

我们首先来看一张数据结构的二进制图,如下:

b321c4765f10cbee43f4defcbe16865b.png

图1

如图1,乍一看可能看不懂,我先来解释一下:

  • 图1最上面表示的是二进制的位(bit),从左到右一共32位,虚线框矩形代表占据了多少位。图中的内容是一行一行显示的(图中共6行),实际上它们应该都处在一行,只是因为这张图太窄了,一行最大只能表示32位,所以才折行了;
  • FIN、RSV1、RSV2、RSV3各占一位,opcode占4位,mask占一位、payload len占7位,如果payloadlen=126,Extended payload length占16位,如果payloadlen=127,Extended payload length占64位,如果mask=1,masking-key占32位,后面再存放payload Data;
  • 虽然websocket可以发送文本,但最终都会转化成二进制收发,在处理时都使用Buffer进行操作,Buffer在之前的文章中已经详细介绍了,如果不了解的可以去翻看一下;
  • Buffer的一位就是一个字节(8位),使用16进制表示。

在传输中,需要把数据转换成二进制,然后按照上面的规则进行解析或者拼接,才能进行正常的通信。

浏览器提供的websocket接口就是按照这种格式发送和解析数据的,不需要关心浏览器内部怎么做的,我只需要来分析一下服务器发送和解析数据的过程,因为它们的方式是一致的。

服务器发送数据

我们结合图1看看如何发送数据,如下图,

4fac7eededd09cd995b03bd110231d61.png

图2

图2中封装了一个send方法,用于服务器发送数据,首先判断数据data是否为字符串,当data是字符串时,opcode=1,当data是二进制时,opcode=2。这里opcode与fin也是有关系的,fin=1表示最后一帧数据,等于0表示后面还有数据,不是第一帧数据的opcode=0,opcode=0代表后续帧。

ce5b5abead90375e8e02ed108ccb524f.png

图3

图3中第一次发送数据,fin=0,opcode=1,4s之后发送第二次数据,fin=1,opcode=0,虽然两次发送数据间隔4s,但是终端会把两次的数据拼接在一起同一时间显示出来,因为终端通过解析fin和opcode发现这两次数据是一起的。

接下来,我们开始按照图1数据格式进行拼接,如下:

7580decccb2c9492a3a6d1462f9d3c24.png

图4

mask表示是否需要掩码,只适用于客户端发送给服务器的消息(mask=1),这里是服务器发送数据,所以mask=0,offset=2,表示最初的两个字节(一共16位)。前四位中fin可以是1或者0,rsv1可以为1但是为了演示方便只考虑0、rsv2和rsv3必须为0,第五位到第八位表示opcode,这是一个可以用4位二进制表示的数字,所以前八位可以用图4中的区域2表示。

当数据的长度<=125,接下来一个字节直接用来表示数据长度;

当数据的长度<65536 && >125,payloadLength会等于126,此时payloadLength对应的数字只是一个标记,接下来需要扩展两个字节,这两个字节会写入数据真实的长度。

当数据的长度>=65536,payloadLength等于127,此时需要扩展8个字节,前四个字节写入的都是0,后面4个字节写入的是数据的长度,所以这里可以看出来数据的长度不能超出4个字节。

这里我们mock一下,当客户端发送给服务器消息时的情况,此时mask=1,如下图,

e77d47d9cb7bc49d45b5a95609b1b8cd.png

图5

与服务器发送数据的区别:

  • offset=6,初始化有6个字节;
  • 图5中区域1,第二个字节的第一位应该置为1,第三到第六个字节应该填入随机码;
  • 图5中区域2,利用这四个随机码给数据都加上掩码(异或);

到这里数据结构已经拼接完成,下面就是把数据发送出去,如下:

193893647156e58d628317077d0f1a83.png

图6

发送方式如图6,因为分两次发送,所以开启了tcp的cork算法,其实也可以把target和data拼接在一起发送。

服务端接受数据

接收数据和发送数据是相反的,如下图:

126fb41c766faaf31c532496c28cc2ea.png

图7

我们可以通过socket的data事件获取客户端发送来的数据,这个数据需要按照图1的数据格式进行解析才能拿到信息。解析的过程我这里就不嗷述了,只要看懂数据是如何发送的,解析其实就是相反的过程!

总结

这篇文章主要讲了websocket是如何发送和接受数据的,并且详细分析了数据结构,虽然比较难懂,但是我觉得还是可以看明白的。

喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!

相关文章:

  • stopwords怎么用_用Python画词云图,展示“新冠肺炎”关键词
  • pygame简单小游戏代码_用pygame实现一个简单的垃圾分类小游戏(已获校级二等奖)!...
  • mysql数据迁移到redis_Mysql到Redis的数据迁移方法
  • linux mysql 客户端 安装配置_linux下mysql的安装部署
  • mysql虚拟表的创建_mysql虚拟表
  • win 10 查看mysql密码_win10系统登录mysql时报错1045?查看解决方案
  • 安装好mysql怎么配置_安装好mysql怎么配置
  • pythonwx关闭窗口_如何在WX python中关闭已打开的窗口
  • mysql负载突然飙升_mysql负载飙高原因分析
  • CA系统mysql_MySQL性能优化
  • linux下安装mysql5.5_Linux下安装mysql5.5.19
  • mysql ignore oracle_Oracle impdp的ignore及 fromuser / touser 功能
  • mysql监控命令_MySQL数据库维护中监控所用到的常用命令
  • python windows api移动窗口_Python使用Windows API创建窗口示例【基于win32gui模块】
  • vue 列表内容自动向上滚动_vue 新闻列表滚动效果
  • avalon2.2的VM生成过程
  • C++11: atomic 头文件
  • C++类中的特殊成员函数
  • Javascript弹出层-初探
  • OSS Web直传 (文件图片)
  • PAT A1092
  • SQLServer之创建显式事务
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 阿里研究院入选中国企业智库系统影响力榜
  • 聊聊redis的数据结构的应用
  • 码农张的Bug人生 - 初来乍到
  • 前端面试题总结
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 阿里云移动端播放器高级功能介绍
  • 交换综合实验一
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • #Z2294. 打印树的直径
  • (12)Hive调优——count distinct去重优化
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (分类)KNN算法- 参数调优
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (规划)24届春招和25届暑假实习路线准备规划
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (三)docker:Dockerfile构建容器运行jar包
  • (四) Graphivz 颜色选择
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .net6使用Sejil可视化日志
  • .NET基础篇——反射的奥妙
  • .skip() 和 .only() 的使用
  • ?php echo ?,?php echo Hello world!;?
  • @拔赤:Web前端开发十日谈
  • []利用定点式具实现:文件读取,完成不同进制之间的
  • []我的函数库
  • [2015][note]基于薄向列液晶层的可调谐THz fishnet超材料快速开关——