WebSocket原理详解(二)

news2025/4/15 5:20:37

WebSocket原理详解(一)-CSDN博客

目录

1.WebSocket协议的帧数据详解

1.1.帧结构

1.2.生成数据帧

2.WebSocket协议控制帧结构详解

2.1.关闭帧

2.2.ping帧

2.3.pong帧

3.WebSocket心跳机制


1.WebSocket协议的帧数据详解

1.1.帧结构

        WebSocket客户端与服务器通信的最小单位是帧(frame),一条完整消息是由一个或多个帧组成的。数据交互时,发送方会将消息切割为多个帧发送给接收方,接收方接收到消息帧后会重新组装为完整的消息。

        当WebSocket接收方接收到一个数据帧时会根据FIN(数据帧中的一个标识,用来判断当前帧是否当前消息的最后一帧)的值来判断是否已经接收到消息的最后一个数据帧。当接收到消息的最后一帧时,即可对消息进行处理。

WebSocket 帧由多个字段组成,各字段按顺序排列,这些字段共同构成了帧的头部和可选的负载数据。帧的基本结构如下:

字段长度(字节)描述
FIN1 位表示该帧是否为消息的最后一帧。1 表示是最后一帧,0 表示还有后续帧。
RSV1 - RSV3各 1 位保留位,默认值为 0。如果要使用,需要在握手阶段进行协商。
Opcode4 位定义帧的操作类型,如文本帧、二进制帧、关闭帧等。
Mask1 位表示负载数据是否经过掩码处理。客户端发送的帧必须进行掩码处理。
Payload length7 位、7 + 16 位或 7 + 64 位表示负载数据的长度。如果值在 0 - 125 之间,直接使用 7 位表示;如果是 126,则后续 2 个字节表示长度;如果是 127,则后续 8 个字节表示长度。
Masking - key0 或 4 字节如果 Mask 位为 1,则存在 4 字节的掩码密钥,用于对负载数据进行掩码处理。

各字段详细解释

1. FIN 字段

  • 作用:用来指示当前帧是否为一个消息的最后一帧。在发送大消息时,消息可能会被拆分成多个帧,FIN 位可以帮助接收方判断消息是否完整。
  • 取值
    • 1:表示这是消息的最后一帧。
    • 0:表示还有后续帧。

2. RSV1 - RSV3 字段

  • 作用:这三个保留位主要是为未来扩展 WebSocket 协议预留的。目前默认值都为 0,如果要使用这些位,需要在握手阶段进行协商。
  • 取值:通常为 0。

3. Opcode 字段

  • 作用:定义了帧的操作类型,接收方根据 Opcode 的值来决定如何处理接收到的帧。
  • 常见取值及含义
    • 0x0:表示延续帧,用于继续之前未完成的消息。
    • 0x1:表示文本帧,负载数据为 UTF - 8 编码的文本。
    • 0x2:表示二进制帧,负载数据为二进制数据。
    • 0x3-0x7:保留帧,留作未来非控制帧扩展使用
    • 0x8:表示关闭帧,用于关闭 WebSocket 连接。
    • 0x9:表示心跳检测的 ping 帧。
    • 0xA:表示心跳检测的 pong 帧,是对 ping 帧的响应。
    • 0xB-0xF:保留帧, 留作未来控制帧扩展使用

4. Mask 字段

  • 作用:指示负载数据是否经过掩码处理。为了提高安全性,客户端发送的帧必须将负载数据进行掩码处理,服务器发送的帧不需要进行掩码处理。
  • 取值
    • 1:表示负载数据经过掩码处理。
    • 0:表示负载数据未经过掩码处理。

5. Payload length 字段

  • 作用:表示负载数据的长度。由于负载数据长度可能不同,该字段采用了可变长度的编码方式。
  • 取值及编码方式
    • 如果值在 0 - 125 之间,直接使用 7 位表示负载数据的长度。
    • 如果值为 126,则后续 2 个字节(16 位)表示负载数据的长度。
    • 如果值为 127,则后续 8 个字节(64 位)表示负载数据的长度。

6. Masking - key 字段

  • 作用:如果 Mask 位为 1,该字段存在,且长度为 4 字节。它是一个随机生成的掩码密钥,用于对负载数据进行掩码处理和解掩码处理。
  • 掩码处理和解掩码处理:假设 P 是原始的负载数据,M 是掩码密钥,C 是经过掩码处理后的数据,则 C[i] = P[i] ^ M[i % 4],接收方可以使用相同的掩码密钥和异或运算对 C 进行解掩码得到 P

7. Payload data 字段

  • 作用:实际传输的数据,可以是文本、二进制数据等,具体取决于 Opcode 的值。

示例

假设客户端要发送一个简单的文本消息 "Hello",以下是一个简化的帧结构分析:

  • FIN:由于这是消息的唯一一帧,FIN 为 1。
  • RSV1 - RSV3:默认值为 0。
  • Opcode:消息是文本,Opcode 为 0x1。
  • Mask:客户端发送的帧需要掩码处理,Mask 为 1。
  • Payload length:消息长度为 5 字节,小于 126,直接用 7 位表示,值为 5。
  • Masking - key:随机生成 4 字节的掩码密钥,例如 0x12345678
  • Payload data:将 "Hello" 进行掩码处理后的数据。

1.2.生成数据帧

        从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的。我们自己需要去生成数据帧,解析数据帧的时候我们需要分片。

消息分片:

        有时候数据需要分成多个数据包发送,需要使用到分片,也就是说多个数据帧来传输一个数据。比如将大数据分成多个数据包传输,分片的目的是允许发送未知长度的消息。这样做的好处是:

  • 大数据的传输可以分片传输,不用考虑到数据大小导致的长度标志位不够的情况
  • 和http的chunk一样,可以边生成数据边传递消息,可以提高传输效率。

        如果大数据不能被碎片化,那么发送端就必须将数据整个载入内存缓冲之中,然后进行计算长度等操作并发送。但是有了碎片化机制,服务器就可以选取适用的内存缓冲长度,然后当缓冲满了之后就发送一个消息碎片。

分片规则:

  • 如果一个消息不分片的话,那么该消息只有一帧(FIN为1,opcode非0);
  • 如果一个消息分片的话,它的构成是由
    • 1个起始帧:FIN为0,opcode非0
    • 然后若干帧:FIN为0,opcode为0
    • 1个结束帧:FIN为1,opcode为0

注意:

  • 当前已经定义的控制帧包括 0x8(close)、0x9(Ping)、0xA(Pong)。控制帧可以出现在分片消息中间,但是控制帧不允许分片,控制帧是通过它的opcode的最高有效位是1去确定的。
  • 组成消息的所有帧都是相同的数据类型,在第一帧中的opcode中指明。组成消息的碎片类型必须是文本,二进制,或者其他的保留类型。

2.WebSocket协议控制帧结构详解

        目前,控制帧的操作码定义了0x08(关闭帧)、0x09(Ping帧)、0x0A(Pong帧)。0x0B-0x0F是为那些将来可能定义而目前尚未定义的控制帧预留的。

        控制帧用于WebSocket协议交换状态信息,控制帧可以插在消息片段之间。

注意:所有的控制帧的负载长度务必不大于125字节,并且禁止对控制帧进行分片处理。

2.1.关闭帧

        关闭帧的操作码Opcode是0x08。

        关闭帧可能包含数据部分(应用数据帧),该部分表明了关闭的原因,例如:端点关闭、端点接收帧过大或端点收到的帧不符合预期。

  • 如果有数据部分,则数据的前两个字节必须是一个无符号整数(网络字节序),该无符号整数表示了一个状态码,具体定义哪些关闭码将在后面的文章中介绍。
  • 在无符号整数后面,可能还有一个UTF-8编码的数据,表示关闭原因,关闭原因由开发者自行定义(可选),并无规范。关闭原因并不一定是对人可读的,但会对调试或传递相关信息起到一定的作用。由于数据不能保证人类可读,所以客户端一定不能将其显示给用户(会在关闭事件onclose中)

        客户端发送给服务器的关闭帧必须掩码处理。应用程序在发送了一个关闭帧后,禁止再发送任何数据(此时处于CLOSING状态)。

        如果端点(客户端或服务器)收到了一个关闭帧,并且之前没有发送过关闭帧,则端点必须发送一个关闭帧作为响应。(当端点发送一个关闭帧回应时,通常会显示它收到的状态码)。当端点可以发送关闭响应时应尽快发送关闭响应。一个端点可以延迟发送响应直到它的当前消息发送完毕(例如,已经发送了大多数的消息片段,则端点可能会在发送关闭响应帧前先将剩下的消息帧发送出去)。但不能保证对方在已经发送了关闭帧后还能够继续处理这些数据。

        在双方都已发送并接收了关闭帧后,端点需要断掉WebSocket连接并且必须关闭底层的TCP连接。服务器必须立即切断底层TCP连接,客户端最好等待服务器断开连接,但也可以在发送并接收了关闭帧后任何时候断开连接,例如在一段时间内服务器仍没有断开TCP连接。

        如果服务器和客户端同时发送了关闭帧,两端都会接收关闭帧,并且都需要断开TCP连接。

关闭帧示例

假设客户端要发送一个关闭帧,状态码为 1000(正常关闭),没有额外的关闭原因。其帧结构如下:

  • FIN:1
  • RSV1 - RSV3:0 0 0
  • Opcode:0x8
  • Mask:1(客户端发送)
  • Payload length:2(状态码占 2 字节)
  • Masking - key:随机生成的 4 字节密钥
  • Payload data:状态码 1000(2 字节)

2.2.ping帧

        Ping帧的操作码为0x09。

        Ping帧可以包含应用数据。

        一旦接到了一个Ping帧,端点必须返回一个Pong帧作为响应,除非它收到了一个关闭帧。它应在可以发送时尽快发送Pong帧响应。

        端点可以在连接建立后一直到连接关闭前任何时候发送Ping帧。

ping 帧示例

客户端发送一个 ping 帧,包含自定义的心跳信息 "HEARTBEAT"。其帧结构如下:

  • FIN:1
  • RSV1 - RSV3:0 0 0
  • Opcode:0x9
  • Mask:1(客户端发送)
  • Payload length:9("HEARTBEAT" 长度为 9)
  • Masking - key:随机生成的 4 字节密钥
  • Payload data:经过掩码处理的 "HEARTBEAT"

2.3.pong帧

        Pong帧的操作码为0x0A。

        Pong帧必须与Ping帧拥有相同的应用数据部分。

        如果端点收到了多个Ping帧,但还没来的及全部回应,可以只回应最后一个Ping帧。

        Pong帧可以在未收到Ping帧时就被发送,用作单向心跳包。

        对未被请求的Pong帧(对方主动发送的Pong帧)进行回应是不需要的。

3.WebSocket心跳机制

        心跳机制的核心是客户端和服务器之间定期发送和接收特定的心跳消息。一般而言,客户端和服务器中的一方会定期发送心跳消息(如 ping 帧),另一方收到后则立即回复相应的响应消息(如 pong 帧)。若在规定时间内未收到响应,就判定连接出现问题,进而进行重连或其他处理。

        WebSocket 协议本身定义了 ping 帧和 pong 帧用于心跳检测。

  • ping 帧:由客户端或服务器发送,用于主动检测对方的连接状态。
  • pong 帧:是对 ping 帧的响应,当一方收到 ping 帧后,必须尽快发送一个 pong 帧,且 pong 帧的负载数据应与 ping 帧的负载数据相同。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2326651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算声音信号波形的谐波

计算声音信号波形的谐波 1、效果 2、定义 在振动分析中,谐波通常指的是信号中频率是基频整数倍的成分。基频是振动的主要频率,而谐波可能由机械系统中的非线性因素引起。 3、流程 1. 信号生成:生成或加载振动信号数据(模拟或实际数据)。 2. 预处理:预处理数据,如去噪…

RepoReporter 仿照`TortoiseSVN`项目监视器,能够同时支持SVN和Git仓库

RepoReporter 项目地址 RepoReporter 一个仓库监视器,仿照TortoiseSVN项目监视器,能够同时支持SVN和Git仓库。 工作和学习会用到很多的仓库,每天都要花费大量的时间在频繁切换文件夹来查看日志上。 Git 的 GUI 工具琳琅满目,Git…

UI设计系统:如何构建一套高效的设计规范?

UI设计系统:如何构建一套高效的设计规范? 1. 色彩系统的建立与应用 色彩系统是设计系统的基础之一,它不仅影响界面的整体美感,还对用户体验有着深远的影响。首先,设计师需要定义主色调、辅助色和强调色,并…

【计算机网络】记录一次校园网无法上网的解决方法

问题现象 环境:实训室教室内时间:近期突然出现 (推测是学校在施工,部分设备可能出现问题)症状: 连接校园网 SWXY-WIFI 后: 连接速度极慢偶发无 IP 分配(DHCP 失败)即使分…

第二十一章:Python-Plotly库实现数据动态可视化

Plotly是一个强大的Python可视化库,支持创建高质量的静态、动态和交互式图表。它特别擅长于绘制三维图形,能够直观地展示复杂的数据关系。本文将介绍如何使用Plotly库实现函数的二维和三维可视化,并提供一些优美的三维函数示例。资源绑定附上…

系统思考反馈

最近交付的都是一些持续性的项目,越来越感觉到,系统思考和第五项修炼不只是简单的一门课程,它们能真正融入到我们的日常工作和业务中,帮助我们用更清晰的思维方式解决复杂问题,推动团队协作,激发创新。 特…

【C++】vector常用方法总结

📝前言: 在C中string常用方法总结中我们讲述了string的常见用法,vector中许多接口与string类似,作者水平有限,所以这篇文章我们主要通过读vector官方文档的方式来学习vector中一些较为常见的重要用法。 🎬个…

2025年数智化电商产业带发展研究报告260+份汇总解读|附PDF下载

原文链接:https://tecdat.cn/?p41286 在数字技术与实体经济深度融合的当下,数智化产业带正成为经济发展的关键引擎。 从云南鲜花产业带的直播热销到深圳3C数码的智能转型,数智化正重塑产业格局。2023年数字经济规模突破53.9万亿元&#xff…

Linux中常用服务器监测命令(性能测试监控服务器实用指令)

1.查看进程 ps -ef|grep 进程名以下指令需要先安装:sysstat,安装指令: yum install sysstat2.查看CPU使用情况(间隔1s打印一个,打印6次) sar -u 1 63.#查看内存使用(间隔1s打印一个,打印6次) sar -r 1 6

基于 GEE 的区域降水数据可视化:从数据处理到等值线绘制

目录 1 引言 2 代码功能概述 3 代码详细解析 3.1 几何对象处理与地图显示 3.2 加载 CHIRPS 降水数据 3.3 筛选不同时间段的降水数据 3.4 绘制降水时间序列图 3.5 计算并可视化短期和长期降水总量 3.6 绘制降水等值线图 4 总结 5 完整代码 6 运行结果 1 引言 在气象…

曲线拟合 | Matlab基于贝叶斯多项式的曲线拟合

效果一览 代码功能 代码功能简述 目标:实现贝叶斯多项式曲线拟合,动态展示随着数据点逐步增加,模型后验分布的更新过程。 核心步骤: 数据生成:在区间[0,1]生成带噪声的正弦曲线作为训练数据。 参数设置&#xff1a…

Qt6调试项目找不到Bluetooth Component蓝牙组件

错误如图所示 Failed to find required Qt component "Bluetooth" 解决方法:搜索打开Qt maintenance tool 工具 打开后,找到这个Qt Connectivity,勾选上就能解决该错误

JAVA- 锁机制介绍 进程锁

进程锁 基于文件的锁基于Socket的锁数据库锁分布式锁基于Redis的分布式锁基于ZooKeeper的分布式锁 实际工作中都是集群部署,通过负载均衡多台服务器工作,所以存在多个进程并发执行情况,而在每台服务器中又存在多个线程并发的情况,…

Java Spring Boot 与前端结合打造图书管理系统:技术剖析与实现

目录 运行展示引言系统整体架构后端技术实现后端代码文件前端代码文件1. 项目启动与配置2. 实体类设计3. 控制器设计4. 异常处理 前端技术实现1. 页面布局与样式2. 交互逻辑 系统功能亮点1. 分页功能2. 搜索与筛选功能3. 图书操作功能 总结 运行展示 引言 本文将详细剖析一个基…

深入剖析JavaScript多态:从原理到高性能实践

摘要 JavaScript多态作为面向对象编程的核心特性,在动态类型系统的支持下展现了独特的实现范式。本文深入解析多态的三大实现路径:参数多态、子类型多态与鸭子类型,详细揭示它们在动态类型系统中的理论基础与实践意义。结合V8引擎的优化机制…

GalTransl开源程序支持GPT-4/Claude/Deepseek/Sakura等大语言模型的Galgame自动化翻译解决方案

一、软件介绍 文末提供程序和源码下载 GalTransl是一套将数个基础功能上的微小创新与对GPT提示工程(Prompt Engineering)的深度利用相结合的Galgame自动化翻译工具,用于制作内嵌式翻译补丁。支持GPT-4/Claude/Deepseek/Sakura等大语言模型的…

TGES 2024 | 基于空间先验融合的任意尺度高光谱图像超分辨率

Arbitrary-Scale Hyperspectral Image Super-Resolution From a Fusion Perspective With Spatial Priors TGES 2024 10.1109/TGRS.2024.3481041 摘要:高分辨率高光谱图像(HR-HSI)在遥感应用中起着至关重要的作用。单HSI超分辨率&#xff…

算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】

算法基础_基础算法【高精度 前缀和 差分 双指针】 ---------------高精度---------------791.高精度加法题目介绍方法一:代码片段解释片段一: 解题思路分析 792. 高精度减法题目介绍方法一:代码片段解释片段一: 解题思路分析 7…

Python数据类型-list

列表(List)是Python中最常用的数据类型之一,它是一个有序、可变的元素集合。 1. 列表基础 创建列表 empty_list [] # 空列表 numbers [1, 2, 3, 4, 5] # 数字列表 fruits [apple, banana, orange] # 字符串列表 mixed [1, hello, 3.14, True] # 混合类型…

如何使用cpp操作香橙派GPIO --使用<wiringPi.h>

香橙派是国产SBC ,对标树莓派。不过国内的开发环境确实挺惨的,没多少帖子讨论。楼主决定从今天起,不定期更新香橙派的教程。 今天的教程是如何使用香橙派下载wiringOP 并使用CPP操作GPIO 操作GPIO 下载wiringPi 检查git 版本克隆wiringPi…