长连接技术

个人学习记录,欢迎指正

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时这个过程和配置对于开发者是无感知的。

  • 请求头:

    字段取值含义是否必设置
    Connectionupgrade希望协议升级必须
    Upgradewebsocket协议应该升级到websocket协议必须
    Sec-Websocket-Key经过base64编码的16字节随机值必须
    Sec-WebSocket-Version版本值websocket版本必须
    Sec-WebSocket-Protocol子协议名称websocket通信时需要的子协议非必须
    Sec-WebSocket-Extensions扩展协议名称websocket通信时的扩展协议非必须
  • 响应头:

    字段取值含义是否必设置
    Sec-WebSocket-AcceptSHA-1哈希值是否支持websocket协议必须
    Sec-WebSocket-Versionwebsocket版本选择支持的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);

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

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

相关文章

企业计算机服务器中了devicdata勒索病毒怎么办,devicdata勒索病毒解密工具流程

随着科学技术的不断发展与应用&#xff0c;越来越多的企业开始利用网络开展各项工作业务&#xff0c;网络为企业的生产运营提供了极大便利&#xff0c;大大提高了生产运营效率&#xff0c;同时也为企业的发展规划带来不错的契机。但网络是一把双刃剑&#xff0c;网络在为人们提…

HAProxy高性能负载均衡器

一、HAProxy基础知识 &#xff08;一&#xff09;HAProxy概述 HAProxy是一款基于事件驱动、单进程模型设计的四层与七层负载均衡器&#xff0c;它能够在TCP/UDP层面以及HTTP(S)等应用层协议上实现高效的流量分发。HAProxy不仅适用于Web服务器负载均衡&#xff0c;还能应用于数据…

AI大浪潮,怎能少了国产HBM内存?

据有关报道显示&#xff0c;武汉新芯半导体制造有限公司&#xff08;XMC&#xff09;正在启动一项专注于开发和生产高带宽内存&#xff08;HBM&#xff09;的项目。 HBM作为一种关键的DRAM类型&#xff0c;对于人工智能&#xff08;AI&#xff09;和高性能计算&#xff08;HPC&…

腾讯云轻量应用服务器2核4G5M代表什么意思?

腾讯云服务器2核4G5M带宽配置是代表什么&#xff1f;代表2核CPU、4G内存、5M公网带宽&#xff0c;这是一款轻量应用服务器&#xff0c;系统盘为60GB SSD云硬盘&#xff0c;活动页面 txybk.com/go/txy 活动打开如下图&#xff1a; 腾讯云2核4G5M服务器 如上图所示&#xff0c;这…

智慧公厕建设的主要目标是什么?

随着城市化进程的不断推进&#xff0c;公共厕所作为城市基础设施的重要组成部分&#xff0c;也变得越来越重要。为了提升公共厕所的管理水平、提供更好的服务质量&#xff0c;智慧公厕应运而生。智慧公厕的建设旨在通过信息化手段实现公共厕所的全面感知监测&#xff0c;实现公…

Jmeter文件上传不成功问题

前言 最近好忙呀&#xff0c;项目上线然后紧接着又客户培训了&#xff0c;由于项目有个模块全是走配置的&#xff0c;所以导致问题不断&#xff0c;近期要培训为了保障培训时客户同时操作的情况&#xff0c;所以把我从功能端抽出来做压测了&#xff0c;之前安排了2个同事写压测…

力扣24. 两两交换链表中的节点

新建虚拟头节点&#xff0c;用3个指针记录前3个节点&#xff0c;然后再相互赋值指向&#xff0c;再移动当前节点&#xff0c;当前节点所在的位置&#xff0c;只能交换该节点的后两个节点&#xff08;所以必须建立虚拟头节点&#xff0c;才能操作第1&#xff0c;2个节点&#xf…

ts版本微信小程序在wxml保存文件不刷新页面的解决办法

将project.config.json中的skylineRenderEnable改为false "skylineRenderEnable": false

python爬虫-AES.CBS加密案例(mmz批量爬取)

下载mmz本页数据 批量下载请看主页&#xff01;&#xff01;&#xff01; 代码&#xff1a; import requests from Crypto.Cipher import AES import base64cookies {PHPSESSID: 48nu182kdlsmgfo2g7hl6eufsa,Hm_lvt_6cd598ca665714ffcd8aca3aafc5e0dc: 1710568549,SECKEY_A…

Redis学习笔记(基础篇)

Redis基础 1 Redis是什么&#xff1f;1.1 键值型1.2 NoSQL1.2.1 NoSQL与SQL的区别是什么1.2.2 总结 1.3 Redis的特点是什么&#xff1f; 2 Redis怎么用&#xff1f;2.1 Redis的基本命令2.2 Key的层级结构2.3 Redis的基本数据类型有哪些&#xff1f;2.1.1 String类型2.1.2 Hash类…

终止代码: DRIVER IRQL NOT LESS OR EQUAL 失败的操作:Netwtw12.sys

蓝屏警告&#xff1a; 今天电脑浏览器用着用着就蓝屏重启&#xff0c;蓝屏上报这个错误&#xff1a; 上网找了一堆&#xff0c;发现关键是这句话&#xff1a;“失败的操作:Netwtw12.sys” 最终在一顿操作下&#xff0c;发现了是23年更新的网卡&#xff08;Intel(R) Wi-Fi6E A…

短剧小程序软件开发首页接口转发到Selectpage

工具&#xff1a;用的是uniapp开发 技术栈&#xff1a;vue、nide..js、云开发 用时&#xff1a;20工作天 软件&#xff1a;Hb、微信开发者工具 <?php namespace app\api\controller; use app\common\controller\Api; /** * 首页接口 */ class Index extends Api { …

【计算机网络】什么是http?

​ 目录 前言 1. 什么是HTTP协议&#xff1f; 2. 为什么使用HTTP协议&#xff1f; 3. HTTP协议通信过程 4. 什么是url&#xff1f; 5. HTTP报文 5.1 请求报文 5.2 响应报文 6. HTTP请求方式 7. HTTP头部字段 8. HTTP状态码 9. 连接管理 长连接与短连接 管线化连接…

基于web的精品课程网站设计

基于web的精品课程网站设计 C#asp.netSqlServer 带论文 功能模块&#xff1a; 基于web的精品课程网站设计 C#asp.netSqlServer 学生功能模块 学生登录系统后&#xff0c;可以在留言板页面给老师进行留言&#xff0c;并且可以查看课程和题库 可以在首页进行考试并且可以修改…

从电影《沙丘》说起——对人工智能的思考

从《沙丘》开始说起 之前看《沙丘》电影&#xff0c;里面有一类角色叫门泰特&#xff0c;这类人大脑可以飞快地运算&#xff0c;在电影设定里是替换人工智能、机器运算的存在。男主保罗也是这类型的人&#xff0c;但他可能基因更强大&#xff0c;吸食了香料后&#xff0c;他的…

力扣111---二叉树的最小深度(简单题,Java,递归+非递归)

目录 题目描述&#xff1a; &#xff08;递归&#xff09;代码&#xff1a; &#xff08;非递归、层次遍历&#xff09;代码&#xff1a; 题目描述&#xff1a; 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说…

1、计划任务介绍

Windows计划任务介绍 1、含义&#xff1a; 简单点就是定时执行任务。 在许多场景下&#xff0c;我们定时执行一些任务。比如&#xff1a;定时拉取、备份文件&#xff0c;更新代码等等操作。 WinR打开运行框&#xff0c;输入&#xff1a;control schedtasks&#xff0c;就会…

大胆投资自己

> Keep Thinking 保持思考 1. 关于投资 首先需要做到 “ 精明 ” 的活着&#xff0c;如何做到精明呢&#xff1f; 所谓精明&#xff0c;也即清醒认识到自己当前所处的阶段&#xff0c;清楚知道下一步的应该朝哪一个方向努力&#xff01;人生就是一场长跑&#xff0c; 我们…

如何订阅Midjourney

Midjourney介绍 Midjourney作为目前AI绘画领域效果卓越且备受青睐的工具&#xff0c;对于新用户而言&#xff0c;可能无法享受到免费试用的机会。因此&#xff0c;为了持续利用这款软件进行绘画创作&#xff0c;用户需要购买会员资格并开通订阅服务。那么&#xff0c;关于midj…

【Godot 4.2】常见几何图形、网格、刻度线点求取函数及原理总结

概述 本篇为ShapePoints静态函数库的补充和辅助文档。ShapePoints函数库是一个用于生成常见几何图形顶点数据&#xff08;PackedVector2Array&#xff09;的静态函数库。生成的数据可用于_draw和Line2D、Polygon2D等进行绘制和显示。因为不断地持续扩展&#xff0c;ShapePoint…