websocket 实现原理和技术方案

news/发布时间2024/5/19 8:01:56

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.bcls.cn/VBHa/1974.shtml

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

相关文章

IO进程线程day5作业

1、使用多线程完成两个文件的拷贝&#xff0c;第一个线程拷贝前一半&#xff0c;第二个线程拷贝后一半&#xff0c;主线程回收两个线程的资源 代码&#xff1a; #include<myhead.h>//定义文件拷贝函数 int copy_file(int start,int len) {int srcfd,destfd;//以只读的形…

Job 和 DaemonSet

一、Job 1、Job 背景问题 K8s 里&#xff0c;最小的调度单元是 Pod&#xff0c;如果直接通过 Pod 来运行任务进程&#xff0c;会产生以下几种问题&#xff1a; ① 如何保证 Pod 内进程正确的结束&#xff1f; ② 如何保证进程运行失败后重试&#xff1f; ③ 如何管理多个任…

阿里云OTA升级指南

阿里云OTA升级指南 OTA简介 OTA是Over-The-Air的缩写&#xff0c;中文意为“通过空中传输”。在计算机和通信技术领域中&#xff0c;OTA指的是通过无线网络等方式将软件、固件、配置文件等更新、下载、安装到设备上的一种技术手段。它可以实现远程升级和管理设备的软件和配置…

【k8s初始化过程解析】

k8s初始化过程解析 [rootk8s-master ~]# kubeadm init –apiserver-advertise-address10.10.10.100 –image-repository registry.aliyuncs.com/google_containers –kubernetes-version v1.25.0 –service-cidr10.1.0.0/16 –pod-network-cidr10.2.0.0/16 –cri-socket …

Vue路由缓存问题

路由缓存问题的产生 VueRouter允许用户在页面中创建多个视图&#xff08;多级路由&#xff09;&#xff0c;并根据路由参数来动态的切换视图。使用带参数的路由时&#xff0c;相同的组件实例将被重复使用。因为两个路由都渲染同一个组件&#xff0c;比起销毁再创建&#xff0c;…

鸿蒙Next怎么升级,有便捷的方法?

早在2023年11月&#xff0c;市场上有自媒体博主表示&#xff0c;华为HarmonyOS NEXT的升级计划是2X年底到2X年初完成一亿部&#xff0c;2X年底完成三亿部。虽然该博主没有明确具体年份&#xff0c;但预计是2024年底2025年初升级一亿部HarmonyOS NEXT设备&#xff0c;2025年底完…

一个基于.NET Core开源、跨平台的仓储管理系统

前言 今天给大家推荐一个基于.NET Core开源、跨平台的仓储管理系统&#xff0c;数据库支持MSSQL/MySQL&#xff1a;ZEQP.WMS。 仓储管理系统&#xff08;WMS&#xff09;介绍 仓储管理系统&#xff08;Warehouse Management System&#xff0c;WMS&#xff09;是一种用于管理…

springboot+flowable 使用方式

创建flowble制定流程图 登录flowalbe 制定流程图 进入建模器应用程序 创建流程图 分配用户 下载流程图 使用springboot 调用flowable /*** 导入流程图老师流程*/Testvoid startTeacherApprover(){Deployment deploy repositoryService.createDeployment().addClasspathRes…

【C++语法基础】3.常用数学运算和位运算技巧(✨新手推荐阅读)

前言 在C编程中&#xff0c;数学运算是非常基础和常用的功能。C提供了多种数学运算符和函数&#xff0c;用于执行基本的数学计算&#xff0c;如加减乘除、取模运算以及位运算等。 一、加减乘除四则运算 C中的基本算术运算符包括加法()、减法(-)、乘法(*)、除法(/)。这些运算…

使用多线程完成两个文件的拷贝,第一个线程拷贝前一半,第二个线程拷贝后一半,主线程回收两个线程的资源

#include <myhead.h> typedef struct {const char *srcfile;const char *destfile;int len;}info;void *task1(void *arg) {info buf*((info *)(arg));//打开这两个文件&#xff0c;只读的形式int fd-1;if((fdopen(buf.srcfile,O_RDONLY))-1){perror("open error&qu…

总结Rabbitmq的六种模式

RabbitMQ六种工作模式 RabbitMQ是由erlang语言开发&#xff0c;基于AMQP&#xff08;Advanced Message Queue 高级消息队列协议&#xff09;协议实现的消息队列&#xff0c;它是一种应用程序之间的通信方法&#xff0c;消息队列在分布式系统开发中应用非常广泛。 RabbitMQ有六…

CSS之BFC

BFC概念 BFC&#xff08;Block Formatting Context&#xff09;即块级格式化上下文&#xff0c;是Web页面的可视CSS渲染的一部分。它是一个独立的渲染区域&#xff0c;让其中的元素在布局上与外部的元素互不影响。简单来说&#xff0c;BFC提供了一个环境&#xff0c;允许内部的…

⭐北邮复试刷题105. 从前序与中序遍历序列构造二叉树__递归分治 (力扣每日一题)

105. 从前序与中序遍历序列构造二叉树 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,…

网站管理新利器:免费在线生成 robots.txt 文件!

&#x1f916; 探索网站管理新利器&#xff1a;免费在线生成 robots.txt 文件&#xff01; 你是否曾为搜索引擎爬虫而烦恼&#xff1f;现在&#xff0c;我们推出全新的在线 robots.txt 文件生成工具&#xff0c;让你轻松管理网站爬虫访问权限&#xff0c;提升网站的可搜索性和…

中期国际2.19黄金市场分析:美国通胀数据火热,黄金面临高利率削弱的挑战

周一(2月19日)亚市&#xff0c;现货黄金震荡走高&#xff0c;目前交投于2018.32美元/盎司左右&#xff0c;涨幅约为0.25%。上周五金价收涨0.46%&#xff0c;报价2013.46美元/盎司&#xff0c;虽然黄金周五略有上涨&#xff0c;但由于通胀数据炽热&#xff0c;美联储提前降息的可…

pikachu靶场-暴力破解

目录 1.基于表单的暴力破解&#xff1a; 2.验证码绕过(on server)&#xff1a; 3.验证码绕过(on client)&#xff1a; 1.基于表单的暴力破解&#xff1a; 个人理解&#xff1a;无验证码和各种校验程序&#xff0c;最为简单的暴力破解。 随便输入错误的账密&#xff0c;burp抓…

Linux 权限详解

目录 一、权限的概念 二、权限管理 三、文件访问权限的相关设置方法 3.1chmod 3.2chmod ax /home/abc.txt 一、权限的概念 Linux 下有两种用户&#xff1a;超级用户&#xff08; root &#xff09;、普通用户。 超级用户&#xff1a;可以再linux系统下做任何事情&#xff…

【AI大语言模型】ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

文生视频模型调研

文生视频只有OpenAI的Sora&#xff0c;其他的&#xff08;&#xff09;都是动图。 OpenAI发布了可以生成60s视频的Sora模型。刚刚发布的google的Gemini pro 1.5就一下子变得无人问津了&#xff0c;太尴尬了。 在这之前视频生成的天花板是Runway&#xff0c;支持最多18s视频生成…

react使用Map方法遍历列表不显示的问题

问题&#xff1a; 在最开始搭建选项卡的时候&#xff0c;我的js代码是这样的 import React, { Component } from react import ./css/02-maizuo.css export default class App extends Component {state {list: [{id: 1,text: 电影},{id: 2,text: 影院}, {id: 3,text: 我的}…
推荐文章