长连接技术
个人学习记录,欢迎指正
1.轮询
1.1 轮询的形式
短连接轮询
前端每隔一段时间向服务端发起一次Http请求来获取数据。
const shortPolling = () => { const intervalHandler = setInterval(() => {fetch('/xxx/yyy').then(response => response.json()).then(response => {/* 自定义短轮询成功标记 */if(response?.code === '1') {/* 自定义工作代码 *//* 结束短轮询 */ clearInterval(intervalHandler) } }) }, 5000); }长连接轮询
前端向服务端发起一次Http请求,当接收到响应体时重新发起请求来获取数据。
const longPolling = () => {fetch('/xxx/yyy').then(response => response.json()).then(data => {/* 自定义工作代码 *//* 继续长轮询 */longPolling();}) }
1.2 轮询的实现
基于Ajax技术轮询
在1中已经举了关于基于ajax技术实现长轮询和短轮询的例子
基于Iframe的轮询
古老的轮询方式,需要装填数据到jsp,php等形式文档中,没有实现前后端分离开发。
插入: 前端在页面中插入一个隐藏的iframe,iframe的src设置为后端接口地址。
填充: 接口返回数据格式为html,服务端用传统web开发形式向html中插入数据,例如php,jsp。
通信: 返回的html在iframe中运行,通过postMessage与原页面进行通信。
轮询: 原页面收到数据后重新加载iframe进行下次轮询(可以根据策略进行长轮询或短轮询)。
基于Jsonp的轮询
古老的轮询方式,请求失败时无法通过删除标签关闭连接。
插入: 前端在页面中插入一个script标签,src设置为后端接口地址,参数上拼接回调函数名称,当接收到数据后调用之。
填充: 接口返回可执行脚本,脚本最后调用回调函数,便于通知数据已接收到。
通信: 通过回调函数通信。
轮询: 接收到数据后前端重新发起Jsonp轮询,删除标签后插入新的标签继续请求(根据需求进行长轮询或短轮询)。
2.iframe长连接
原理
例如使用http1.x进行通信,服务端在发送响应信息后不关闭信道(在nodejs中即不写
res.end()),每隔一段时间向客户端发送一次消息。这个可以利用服务端持续向iframe输入文档实现。如果使用fetch,xhr,那么无法直接实现,它们只能支持接收一次消息。(目前一般不使用iframe这种古老做法)
前端代码
<html> <head><meta charset="UTF-8" /> </head> <body><div id="display-div"></div><button onclick="handleStartConnect()">开始连接</button><button onclick="handleStopConnect()">断开连接</button><script type="text/javascript">// 开始连接const handleStartConnect = () => {const iframe = document.createElement("iframe");iframe.id = "iframe-connector";iframe.src = "/iframeLongConnection";iframe.style.display = "none";document.body.append(iframe);};// 断开连接const handleStopConnect = () =>document.querySelector("#iframe-connector").remove();// 收集长连接信息 window.addEventListener("message", (event) => {document.querySelector("#display-div").innerHTML = event.data;});</script> </body> </html>服务器代码
let fs = require("fs");// 服务器基本服务 const read = (path, res) => { // 支持读取html和js fs.readFile(path, (err, data) => {if (err) console.log(err);else {res.writeHead(200, {"Content-Type":path.slice(-2, path.length) === "js"? "text/javascript": "text/html",});res.write(data);res.end();} }); };// 输入到iframe中的模板 const getTemplate = () => { const template = `<script type="text/javascript">window.parent.postMessage(new Date().toLocaleTimeString(), "http://localhost:3000/index.html");</script> `; return template; };// 服务端定时器维持长连接 const circulate = (res) => { res.writeHead(200, { "Content-Type": "text/html" }); setInterval(() => {res.write(getTemplate()); }, 1000); };require("http") .createServer(function (req, res) {// 处理图标if (req.url === "/favicon.ico") res.end();// 长连接测试else if (req.url === "/iframeLongConnection") circulate(res);// 服务器基本服务else read("." + req.url, res); }) .listen(3000, function (err) {if (err) console.log(err);else console.log("运行成功"); });
4.Websocket长连接
4.1 Websocket实现
4.1 综述
技术综述:
websocket是协议,是对http协议的升级。
websocket基于TCP协议,也是使用80端口。
功能特点:
- 前端实现简单,只需要建立连接,监听屈指可数的几个事件。
- 支持全双工通信。服务端和客户端可以互相发送消息。
- 不局限于web端。其它终端设备或应用程序也可以使用该协议。
4.2 web端Websocket事件和方法
事件 描述 open 连接建立 close 连接关闭 error 发生错误 message 接收信息
实例方法 描述 send 发送消息 close 关闭连接 4.3 服务端Websocket的事件和方法
服务端实现websocket通常采用第三方库,不同的第三方库对方法和事件的规定各不相同,在此不做具体介绍。
4.4 客户端代码实现
<html> <head><meta charset="UTF-8" /> </head> <body><button onclick="handleBuild()">建立连接</button><button onclick="socket.close()">断开连接</button><button onclick="socket.send(123)">发送一条消息</button><script type="text/javascript">let socket = null;// 连接相关事件监听函数const handleMessage = (event) => alert(event.data);const handleOpen = () => alert("连接成功");const handleError = () => alert("连接错误");const handleClose = () => {alert("连接关闭");socket.removeEventListener("open", handleOpen);socket.removeEventListener("close", handleClose);socket.removeEventListener("error", handleError);socket.removeEventListener("message", handleMessage);};// 建立连接const handleBuild = () => {socket = new WebSocket("ws://localhost:3001/testSocket");socket.addEventListener("open", handleOpen);socket.addEventListener("close", handleClose);socket.addEventListener("error", handleError);socket.addEventListener("message", handleMessage);};// 关闭连接const handleDestroy = () => socket.close();// 发送消息const sendMessage = (message) => socket.send(JSON.stringify(message));</script> </body> </html>4.5 服务端代码实现
const fs = require("fs"); const ws = require("nodejs-websocket");// 基本读写服务 const read = (path, res) => {// 支持读取html和jsfs.readFile(path, (err, data) => {if (err) console.log(err);else {res.writeHead(200, {"Content-Type":path.slice(-2, path.length) === "js"? "text/javascript": "text/html",});res.write(data);res.end();}}); };require("http").createServer(function (req, res) {// 处理图标if (req.url === "/favicon.ico") res.end();else read("." + req.url, res);}).listen(3000, function (err) {if (err) console.log(err);else console.log("运行成功");});const wsServer = ws.createServer((conn) => {// 接收信息conn.on("text", (text) =>conn.sendText(`服务端已收到信息,您的信息是${text}`));// 连接错误conn.on("error", () => console.log("连接错误"));// 连接关闭conn.on("close", () => console.log("连接断开")); });wsServer.on("connection", () => console.log("新连接建立")); wsServer.listen(3001);
4.2 Websocket建立与销毁
Http握手
Websocket连接建立需要Http1.1或以上版本的get方法握手,这个过程在浏览器调试栏中无法抓包得到,只能抓包分析Websocket协议。
在前端和后端实现websocket时这个过程和配置对于开发者是无感知的。
请求头:
字段 取值 含义 是否必设置 Connection upgrade 希望协议升级 必须 Upgrade websocket 协议应该升级到websocket协议 必须 Sec-Websocket-Key 经过base64编码的16字节随机值 必须 Sec-WebSocket-Version 版本值 websocket版本 必须 Sec-WebSocket-Protocol 子协议名称 websocket通信时需要的子协议 非必须 Sec-WebSocket-Extensions 扩展协议名称 websocket通信时的扩展协议 非必须 响应头:
字段 取值 含义 是否必设置 Sec-WebSocket-Accept SHA-1哈希值 是否支持websocket协议 必须 Sec-WebSocket-Version websocket版本 选择支持的websocket版本 必须 Sec-WebSocket-Protocol 子协议名称 选择支持的子协议 非必须 Sec-WebSocket-Extensions 扩展协议名称 选择支持的扩展协议名称 非必须 响应状态码:
响应状态码为101时表示可以使用websocket协议
Sec-Websocket-Key验证:
验证过程类似于加密解密。 客户端传给服务端Sec-Websocket-Key,服务端将这个key和一个规定的并且是固定的Websocket魔数(字符串)拼接。之后服务端将这个拼接的字符串输入SHA-1哈希算法,得到哈希值。最后服务端将哈希值返回给客户端,客户端用同样方式解密来判断服务端是否支持websocket协议。
挥手
服务端发出关闭连接的消息或客户端发来关闭连接的消息后将关闭websocket连接
5.SSE长连接
5.1 综述
技术综述:
SSE是一种基于Http协议的技术,不是一种新的协议。
功能特点:
- 前端需要实现代码不多。
- 由于只是使用Http协议,因此前后端的配置会比使用Websocket协议简单些。
- 由于只是使用Http协议,因此只能服务端向前端推送消息,相比Websocket协议的长连接像阉割版。
性能限制:
同一个浏览器同一个域的Http连接最多支持并发6个,如果长时间用SSE技术保持长连接,会降低该域的并发连接数量。
5.2 客户端代码实现
<html><head><meta charset="UTF-8" /></head><body><div id="message-collector"></div><button onclick="handleBuild()">建立连接</button><button onclick="SSETarget.close()">关闭连接</button><script type="text/javascript">let SSETarget = null;const handleBuild = () => {SSETarget = new EventSource("http://localhost:3002/sseStream");SSETarget.addEventListener("open", () => alert("数据链路可以通信"));SSETarget.addEventListener("error", () => alert("数据链路发生错误"));// 接收数据SSETarget.addEventListener("message",(event) =>(document.querySelector("#message-collector").innerHTML =event.data));// 监听服务端配置的自定义事件SSETarget.addEventListener("testEvent", (event) => console.log(event));};</script></body> </html>5.3 服务端代码实现
- 响应类型: 保证返回的数据类型是
text/event-stream。- 响应数据结构: 保证换行返回,保证数据是
xxx: yyy形式返回,xxx可取值有event, data, id等等,分别表示描述事件的响应,描述数据内容的响应,描述数据id的响应。// 服务器基本读写服务 const read = (path, res) => {// 支持读取html和jsrequire("fs").readFile(path, (err, data) => {if (err) console.log(err);else {res.writeHead(200, {"Content-Type":path.slice(-2, path.length) === "js"? "text/javascript": "text/html",});res.write(data);res.end();}}); };require("http").createServer((req, res) => {// SSE技术服务端简单实现if (req.url === "/sseStream") {res.writeHead(200, {// 必须得返回类型"Content-Type": "text/event-stream"});res.write("retry: 10000\n");// 自定义一个事件res.write("event: testEvent\n");// 在该自定义事件下发送信息给客户端res.write("id: " + "testId\n\n");res.write("data: " + new Date() + "\n\n");interval = setInterval(() => {res.write("event: message\n");res.write("id: " + "messageId\n\n");res.write("data: " + new Date() + "\n\n");}, 1000);req.connection.addListener("close", () => clearInterval(interval), false);} // 处理图标else if (req.url === "/favicon.ico") res.end();// 服务器基本服务else read("." + req.url, res);}).listen(3002);
相关文章:
长连接技术
个人学习记录,欢迎指正 1.轮询 1.1 轮询的形式 短连接轮询 前端每隔一段时间向服务端发起一次Http请求来获取数据。 const shortPolling () > { const intervalHandler setInterval(() > {fetch(/xxx/yyy).then(response > response.json()).then(respo…...
供电系统分类详解
一、供电系统分类 电力供电系统一般有5种供电模式,常用的有:IT系统,TT系统,TN系统,其中TN系统又可以分为TN-C,TN-S,TN-C-S。 1、TN-C系统(三相四线制) 优点: 该系统中…...
基于centos7的k8s最新版v1.29.2安装教程
k8s概述 Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。 Kubernetes 这个名字源于希腊语&…...
【赠书第20期】AI绘画与修图实战:Photoshop+Firefly从入门到精通
文章目录 前言 1 入门篇:初识Photoshop与Firefly 2 进阶篇:掌握Photoshop与Firefly的核心技巧 3 实战篇:运用Photoshop与Firefly进行创作 4 精通篇:提升创作水平,拓展应用领域 5 结语 6 推荐图书 7 粉丝福利 前…...
如何在并行超算云上玩转PWmat③:使用Q-Flow提交计算的案例演示
3月的每周二下午14:00我们将会在并行直播间为大家持续带来线上讲座。前面两期我们分享了”PWmat特色功能和应用“以及“如何在并行超算云平台使用PWmat计算软件”主题讲座,回看视频和PPT已上传至B站”龙讯旷腾“账号内。 本周张持讲师将继续带着大家手把手上机教学…...
html5cssjs代码 017样式示例
html5&css&js代码 017样式示例 一、代码二、解释 这段HTML代码定义了一个网页的基本结构,包括头部、主体和尾部。在头部中,设置了网页标题、字符编码和样式。主体部分包含一个标题和一个表格,表格内分为两个单元格,左侧为…...
Vue.js动画
Vue.js动画 Vue.js动画是指在Vue组件中通过添加/移除CSS类或应用CSS过渡/动画效果来实现的视觉效果。这些动画可以帮助改善用户体验,使界面更加生动和吸引人。 Vue.js提供了两种类型的动画:过渡和动画。 过渡:过渡是在元素插入、更新或删除…...
信号与系统学习笔记——信号的分类
目录 一、确定与随机 二、连续与离散 三、周期与非周期 判断是否为周期函数 离散信号的周期 结论 四、能量与功率 定义 结论 五、因果与反因果 六、阶跃函数 定义 性质 七、冲激函数 定义 重要关系 作用 一、确定与随机 确定信号:可以确定时间函数…...
PyTorch深度学习实战(39)——小样本学习
PyTorch深度学习实战(39)——小样本学习 0. 前言1. 小样本学习简介2. 孪生网络2.1 模型分析2.2 数据集分析2.3 构建孪生网络 3. 原型网络3. 关系网络小结系列链接 0. 前言 小样本学习 (Few-shot Learning) 旨在解决在训练集中只有很少样本的情况下进行分…...
论文阅读——Vision Transformer with Deformable Attention
Vision Transformer with Deformable Attention 多头自注意力公式化为: 第l层transformer模块公式化为: 在Transformer模型中简单地实现DCN是一个non-trivial的问题。在DCN中,特征图上的每个元素都单独学习其偏移,其中HWC特征图上…...
AJAX概念和axios使用、URL、请求方法和数据提交、HTTP协议、接口、form-serialize插件
AJAX概念和axios使用 AJAX概念 AJAX就是使用XMLHttpRequest对象与服务器通信,它可以使用JSON、XML、HTML和text文本等格式发送和接收数据,AJAX最吸引人的就是它的异步特性,也就是说它可以在不重新刷新页面的情况下与服务器通信,…...
【R语言基础操作】
🍉CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一|统计学|干货分享 擅长Python、Matlab、R等主流编程软件 累计十余项国家级比赛奖项,参与研究经费10w、40w级横向 文…...
sqlite 常见命令 表结构
在 SQLite 中,将表结构保存为 SQL 具有一定的便捷性和重要性,原因如下 便捷性: 备份和恢复:将表结构保存为 SQL 可以方便地进行备份。如果需要还原或迁移数据库,只需执行保存的 SQL 脚本,就可以重新创建表…...
基于深度学习的车辆检测技术
基于深度学习的车辆检测技术是现代智能交通系统的重要组成部分,它利用计算机视觉和机器学习算法,特别是深度学习模型,来识别和定位图像或视频中的车辆。这项技术广泛应用于自动驾驶、交通监控、违章抓拍等多个领域。 深度学习车辆检测技术的…...
MyBatis 之三:配置文件详解和 Mapper 接口方式
配置文件 MyBatis 的配置文件是 XML 格式的,它定义了 MyBatis 运行时的核心行为和设置。默认的配置文件名称为 mybatis-config.xml,该文件用于配置数据库连接、事务管理器、数据源、类型别名、映射器(mapper 文件)以及其他全局属性…...
【PyTorch】基础学习:一文详细介绍 torch.load() 的用法和应用
【PyTorch】基础学习:一文详细介绍 torch.load() 的用法和应用 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程ὄ…...
事务、并发、锁机制的实现
配置全局事务 DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: mydb,USER:root,PASSWORD:pass,HOST:127.0.0.1,PORT:3306,ATOMIC_REQUESTS: True, # 全局开启事务,绑定的是http请求响应整个过程# (non_atomic_requests可局部实现不让事务控制)} } …...
PC-DARTS: PARTIAL CHANNEL CONNECTIONS FOR MEMORY-EFFICIENT ARCHITECTURE SEARCH
PC-DARTS:用于内存高效架构搜索的部分通道连接 论文链接:https://arxiv.org/abs/1907.05737 项目链接:https://github.com/yuhuixu1993/PC-DARTS ABSTRACT 可微分体系结构搜索(DARTS)在寻找有效的网络体系结构方面提供了一种快速的解决方案…...
git的下载与安装
下载 首先,打开您的浏览器,并输入Git的官方网站地址 点击图标进行下载 下载页面会列出不同操作系统和平台的Git安装包。根据您的操作系统(Windows、macOS、Linux等)和位数(32位或64位),选择适…...
windows文档格式转换的实用工具
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...


