websocket 实现原理和技术方案

websocket

WebSocket 是 HTML5 开始提供的一种浏览器与服务器进行全双工通讯的网络技术,用以取代轮询与长连接,使客户端浏览器具备像 C/S 框架下桌面系统的即使通讯能力

websocket协议是建立在tcp协议之上的,建立连接需要三次握手。

websocket协议的连接过程:

  1. 客户端连接服务器(TCP / IP),三次握手,建立了连接通道
  2. 客户端发送一个http格式的消息(特殊格式),服务器也响应一个http格式的消息(特殊格式),称之为http握手
  3. 客户端与服务器完成握手,开始双向通信
  4. 客户端或服务器断开,通道销毁

特点

  1. 建立在tcp协议之上的,建立连接需要三次握手
  2. 通信格式是二进制,可以传输任意数据
  3. 通信格式是http协议,可以传输任意数据

因为 websocket 是基于(TCP / IP)协议,所以我们的代码示例使用nodejs的net模块。我们的示例代码只演示了websocket的握手过程,并没有实现完整的通信。如果想要实现完整的通信,需要深入理解WebSocket协议的工作原理,包括消息帧的解析、心跳机制、分片消息的传输等等。可以参考以下内容

RFC6455:websocket规范

规范:数据帧掩码细节

规范:数据帧格式

server-example

编写websocket服务器

对网络基础设施的攻击(数据掩码操作所要预防的事情)

What is Sec-WebSocket-Key for?

10.3. Attacks On Infrastructure (Masking)

Why are WebSockets masked?

How does websocket frame masking protect against cache poisoning?

What is the mask in a WebSocket frame?

代码示例

客户端

// 创建websocket连接
const ws = new WebSocket('ws://127.0.0.1:8989')
// 监听连接成功事件
ws.onopen = function () {console.log('连接成功');
}
// 监听接受消息事件
ws.onmessage = function (e) {console.log('接受消息');
}
// 监听连接关闭事件
ws.onclose = function () {console.log('连接关闭');
}
// 监听连接失败事件
ws.onerror = function () {console.log('连接失败');
}

服务器

const net = require('net');
const server = net.createServer((socket) => {console.log("收到客户端的连接");socket.once('data', (chunk) => {const hearder = parseRequestHeader(chunk.toString('utf-8'));const crypto = require("crypto");const hash = crypto.createHash("sha1");hash.update(hearder['Sec-WebSocket-Key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");const key = hash.digest("base64");socket.write(`HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ${key}`);socket.on('data', (chunk) => {console.log(chunk);})});
});
server.listen(5008);/*** 解析请求头* @param {string} hearderStr */
function parseRequestHeader(hearderStr = '') {const hearders = hearderStr.split('\r\n');hearders.shift();return Object.fromEntries(hearders.filter(hearder => hearder).map(hearder => {const i = hearder.indexOf(":");return [hearder.substring(0, i), hearder.substring(i + 1).trim()];}));
};

websocket 扩展知识点

websocket 连接服务端,三次握手建立通道,客户端还需要发送一个特殊格式的http请求。
该格式包含 http1.1 协议升级 和 websocket 的请求头。

GET ws://127.0.0.1:5500/public/index.html/ws HTTP/1.1
Host: 127.0.0.1:5500
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://127.0.0.1:5500
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Sec-WebSocket-Key: Re+vR4i5EJmWPU3H7horvg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Sec-WebSocket-Key 和 Sec-WebSocket-Extensions 为 websocket 请求头

Upgrade: websocket 告诉服务端 将 http1.1 协议升级为 websocket 协议
Connection: Upgrade 告诉服务端 连接升级

http1.1 协议升级

HTTP/1.1 协议提供了一种使用 Upgrade (en-US) 标头字段的特殊机制,这一机制允许将一个已建立的连接升级成新的、不相容的协议

这个机制是可选的;它并不能强制协议的更改(通常来说这一机制总是由客户端发起的)。如果它们支持新协议,实现甚至可以不利用 upgrade,在实践中,这种机制主要用于引导 WebSocket 连接。

因为 Upgrade 是一个逐跳(Hop-by-hop)标头,它还需要在 Connection 标头字段中列出

如果服务器决定升级这次连接,就会返回一个 101 Switching Protocols 响应状态码,和一个要切换到的协议的标头字段 Upgrade

HTTP/2 明确禁止使用此机制;这个机制只属于 HTTP/1.1

websocket 请求头

  • Sec-WebSocket-Extensions 用于指定一个或多个请求服务器使用的协议级 WebSocket 扩展。允许在一个请求中使用多个 Sec-WebSocket-Extension 标头;结果跟在一个标头文件中包含了所有列出的扩展一样。

  • Sec-WebSocket-Key 该标头向服务器提供确认客户端有权请求升级到 WebSocket 的所需信息。当不安全(HTTP)客户端希望升级时,可以使用该标头,以提供一定程度防止滥用的保护。密钥的值是使用 WebSocket 规范中定义的算法计算的,不提供安全性。

  • Sec-WebSocket-Version 指定客户端支持的 WebSocket 版本。

  • Sec-WebSocket-Protocol 指定你希望用的一个或者多个 WebSocket 协议。

响应标头

  • Sec-WebSocket-Version 如果服务器无法使用指定版本的 Websocket 协议进行通信,它将响应一个错误(例如 426 Upgrade Required),该错误在它的标头中包含一个 Sec-WebSocket-Version 标头,其中包含支持的逗号分隔列表的协议版本。如果服务器确实支持请求的协议版本,则响应中不包含 Sec-WebSocket-Version 标头

  • Sec-WebSocket-Accept 服务器端响应的标头,用于确认客户端请求。如果提供了 Sec-WebSocket-Key 标头,那么将通过以下流程计算此标头的值:首先取密钥的值,然后将该值与“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”进行拼接,再取拼接后的字符串的 SHA-1 哈希。最后对得出的 20 字节的值进行 base64 编码以获得该属性的值。

第三方库

  • ws
  • ws 是一个快速、易于使用、文档齐全且经过全面测试的 WebSocket 客户端和服务器实现,几乎支持所有浏览器
  • socket.io
  • socket.io 可以在每个平台、每个浏览器和每个设备上工作。

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

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

相关文章

【四】3D Object Model之测量Features——get_object_model_3d_params()算子

😊😊😊欢迎来到本博客😊😊😊 🌟🌟🌟 Halcon算子太多,学习查找都没有系统的学习查找路径,本专栏主要分享Halcon各类算子含义及用法,有…

iMazing2024Windows和Mac的iOS设备管理软件(可以替代iTunes进行数据备份和管理)

iMazing2024是一款兼容 Windows 和 Mac 的 iOS 设备管理软件,可以替代 iTunes 进行数据备份和管理。以下是一些 iMazing 的主要功能和优点: 数据备份和恢复:iMazing 提供了强大的数据备份和恢复功能,可以备份 iOS 设备上的各种数据…

PWM在STM32中使用指南

什么是PWM? PWM(脉冲宽度调制)是一种常用来控制模拟电路的技术,通过修改脉冲的宽度(即在固定周期内的高电平持续时间)来调控输出信号的平均电压。 一个PWM信号主要包括两个部分:一个是占空比,…

四甲基罗丹明-叠氮,5(6)-TAMRA N3,常用的生物标记试剂

您好,欢迎来到新研之家 文章关键词:四甲基罗丹明-叠氮,Tetramethylrhodamine, TMR,5(6)-TAMRA-azide,5(6)-TAMRA N3 一、基本信息 产品简介:5 (6) - TAMRA azide, also known as tetramethylrhodamine a…

智慧安防/视频监控汇聚平台EasyCVR如何通过接口调用获取设备录像回看的流地址?

视频云存储/视频融合/安防监控EasyCVR视频汇聚系统可兼容各品牌的IPC、NVR、移动单兵、智能手持终端、移动执法仪、无人机、布控球等设备的接入,支持的接入协议包括:国标GB28181、RTSP/Onvif、RTMP,以及厂家的私有协议与SDK,如&am…

全流程点云机器学习(二)使用PaddlePaddle进行PointNet的机器学习训练和评估

前言 这不是高支模项目需要嘛,他们用传统算法切那个横杆竖杆流程复杂耗时很长,所以想能不能用机器学习完成这些工作,所以我就来整这个工作了。 基于上文的数据集切分 ,现在来对切分好的数据来进行正式的训练。 本系列文章所用的…

NODEJS + VUE

简单回顾一下之前做的项目: 一、什么是nodejs? 脚本语言需要一个解析器才能运行,JavaScript是脚本语言,在不同的位置有不一样的解析器,如写入html的js语言,浏览器是它的解析器角色。而对于需要独立运行的JS&#xf…

使用 Next.js 连接 mysql 数据库

前言 本文主要为大家介绍,如何使用 Next 框架实现一个简单的后端接口,并且从数据库中请求数据返回给前端。 实现 创建api/getData文件夹 项目创建完成后在 app 文件下新建api文件夹,在 api 文件夹下新建 getData 文件夹,在 ge…

IOT-Reaserch安装ghidra以及IDEA和ghidra的配置

Linux research 5.4.0-91-generic #102~18.04.1-Ubuntu SMP Thu Nov 11 14:46:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux java --version IOT自带的java是符合要求的,不需要额外下载 iotresearch:~/install-file$ java --version openjdk 11.0.13 2021-10-19 …

【LeetCode】509. 斐波那契数(简单)——代码随想录算法训练营Day38

题目链接:509. 斐波那契数 题目描述 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n -…

数字新纪元:探索Web3对社会的影响

在当今数字化时代,技术的进步已经成为社会发展的驱动力之一。而随着区块链技术的快速发展,我们正处在一个即将到来的数字新纪元——Web3时代。这一新时代不仅仅是技术的迭代升级,更是对传统社会模式的颠覆和重构。本文将深入探讨Web3对社会的…

当前主流开发语言有哪些:了解其特性、应用与示例

随着技术飞速发展,编程语言的丰富多样性为开发者提供了广泛的选择。每种语言都有其适用的场景和独特的特性。本文将综合探讨目前市场上最流行、最多人使用的几种主流开发语言,包括它们的特点、典型应用场景以及简单示例代码。 一、Python 特点 Python…

深入理解指针(c语言)

目录 一、使用指针访问数组二、数组名的理解1、数组首元素的地址2、整个数组 三、一维数组传参的本质四、冒泡排序五、二级指针六、指针数组 一、使用指针访问数组 可以使用指针来访问数组元素。例如,可以声明一个指针变量并将其指向数组的第一个元素,然…

Github代码仓库SSH配置流程

作者: Herman Ye Auromix 测试环境: Ubuntu20.04 更新日期: 2024/02/21 注1: Auromix 是一个机器人爱好者开源组织。 注2: 由于笔者水平有限,以下内容可能存在事实性错误。 相关背景 在为Github代码仓库配…

Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动

Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动 文章目录 Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动遮罩效果硬边溶解光边溶解UV扰动 遮罩效果 效果展示: 思路与代码&#xff1…

消息队列-RabbitMQ:死信队列

十五、死信队列 1、死信的概念 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 que…

postgres

1.下载postgres 解压后 bin\initdb -D data -U postgres -A password -E utf8 -W // 初始化设置密码这里的账号是postgres pg_ctl.exe register -N "PostgreSQL" -D "F:/pgsql/data" //windows 本地生成服务 pg_ctl -D F:/pgsql/data -l F:/pgsql/logs/pg…

用idea debug时,怎么在某个map对象中再加个key value

实现方式 在用idea 进行 debug时,我们经常喜欢对某行代码打断点,然后对某个对象重新设置值,以快速地实现我们预期想覆盖的场景。通常的方式是用鼠标右键点击某个对象,然后选择Set value进行设置值,但是如果想在map中添…

鸿蒙原生应用元服务实战-发布时多设备选择注意事项

在可公开可获取DevEco Studio最新版本,Stage模型ArkTSAPI9开发元服务HarmonyOS4现不支持平板等;但是元服务在发布时是可选平板、智慧屏电视设备发布。 如果开发人员与上架运营人员沟通不充分的话,上架运营人员可能会选择多设备发布,试一试&am…

bugku3

xxx二手交易市场 进去是这样讴歌乱进的页面 查看了一下源代码也没什么 先随便注册一个账号 然后登录 随便看了看,发现可以修改头像 上传文件 随便上传了一个图片 发现他对图片进行了base64加密 解密后得到是 data:image/jpeg;base64 这里重新修改类型为php&a…