客户端与服务端实时通讯(轮询、websocket、SSE)

客户端与服务端实时通讯

背景

在某些项目中,某些数据需要展示最新的,实时的,这时候就需要和服务端进行长时间通讯

方案

对于数据实时获取,我们一般会有4种方案:

1.短轮询:使用浏览器的定时器发起http请求,每隔一段时间就请求一次
2.长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
3.websocket:客户端与服务端建立websocket连接,搭建双工(双向)通道
4.SSE(Server-Sent Events):基于HTTP的html5新特性,服务器推送,属于半双工通信模型

轮询

轮询是指客户端定时向服务器发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接。

轮询分为短轮询和长轮询

短轮询

实现原理: 短轮询指客户端每间隔一段时间向服务端发起请求,保持数据的同步。

优点: 可实现基础(指间隔时间较短)的数据更新。

缺点: 这种方法也只是尽量的模拟即时传输,但并非真正意义上的即时通讯,坏处是间隔设置的太长用户体验不好,设置间隔太短后端服务会进行大量的无效查询并且数据没有及时返回前端展示给用户。

长轮询

实现原理: 客户端发送请求后,如果没有数据返回,服务端会将请求放入队列一直连接处理其他请求,直到有数据才返回给客户端,然后客户端再次发起请求,以此轮询。在 HTTP1.0 中客户端可以设置请求头 Connection:keep-alive,服务端收到该请求头之后知道这是一个长连接,在响应报文头中也添加 Connection:keep-alive。客户端收到之后表示长连接建立完成,可以继续发送其他的请求。在 HTTP1.1 中默认使用了 Connection:keep-alive 长连接。
优点: 减少了大量无效的查询,保证每次请求都有数据返回,不会一直占用线程。
缺点: 如果新数据频繁,会进行大量的连接建立和关闭,对服务器的处理能力要求较高。服务器一直保持连接会消耗资源,需要同时维护多个线程,服务器所能承载的 TCP 连接数是有上限的,这种轮询很容易把连接数顶满。每次通讯都需要客户端发起,服务端不能主动推送。

websocket

实现原理: Websocket 实现了客户端与服务端的双向(双工)通信,只需要连接一次,就可以相互传输数据,很适合实时通讯、数据实时更新等场景。
优点:
1.双向通讯:客户端服务端双方都可以主动发起通讯
2.没有同源限制:相对于tcp请求websocket客户端可以与任意服务端通讯,不存在跨域的情况
3.数据量轻:只需要第一次连接时携带请求头,后面的数据通讯都不需要携带请求头
4.传输效率高,因为只需要一次连接
缺点:
1.长连接需要后端处理业务的代码更稳定,推送消息相对复杂
2.长连接对网络要求比较大,需要处理好重连接
3.兼容性差,Websocket只支持IE10及以上

使用

1.客户端代码

  <script>let socket = new WebSocket('ws://localhost:8888')socket.onopen = function () {console.log('1. 客户端连接上了服务器',new Date().getTime());socket.send('3. 你好')}socket.onmessage = function (e) {console.log('6',e.data);}
</script>

2.服务端代码

let express = require('express')
let app = express()
app.use(express.static(__dirname))app.listen(3000)let WebSocket = require('ws')
let wss = new WebSocket.Server({port:8888})
wss.on('connection',function(ws){console.log('2.服务器监听到了客户端的连接',new Date().getTime());ws.on('message',function(data){console.log('4.客户端发来的消息',data);ws.send('5.服务端说:你也好')})
})

SSE(EventSource)

实现原理: 客户端首先向服务器发送一个 HTTP 请求,然后服务器设置响应头并保持这个连接打开,并周期性地通过这个连接向客户端发送数据。每个数据块都是一个独立的消息。

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

优点:
1.简单易用:只需要在客户端创建一个EventSource对象,指定服务器端的URL,即可进行监听并展示事件。
2.网络带宽节省:EventSource采用长连接的方式进行数据传输,相比于普通的轮询方式,能够节省大量的网络带宽。
3.跨域支持:允许在跨域环境下进行通信,通过适当的响应头授权来自不同域的客户端连接。
缺点:
1.单项通信:只支持服务器向客户端的单向通信,无法实现客户端向服务器的实时交互。
2.不能重连:如果网络连接不稳定,或者服务器端关闭EventStream连接,客户端需要重新连接才能继续监听事件。
3.不支持二进制数据传输:只能传输文本数据,不能传输二进制数据,这在某些场景下可能存在一定的局限性。

使用

1.客户端

var eventSource = new EventSource("/clock");
eventSource.onmessage = function(event) {console.log("Received event: " + event.data);
};

2.服务端

let express = require('express')
let app = express()
app.use(express.static(__dirname))let counter = 0
app.get('/clock',function(req,res){res.header('Content-Type','text/event-stream')let $timer = setInterval(() => {// 第一种写法res.write(`id:${counter++}\nevent:message\ndata:${new Date().toLocaleString()}\n\n`)// 另一种写法res.write(`event:yya\n`)     // 触发 自定义事件res.write(`data:${counter}\n\n`)}, 1000 );res.on('close',function(){counter = 0clearInterval($timer)})
})
app.listen(3000)

chatGPT就是使用的这种方式
请添加图片描述
响应头
在这里插入图片描述
响应的数据
在这里插入图片描述

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

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

相关文章

模块化时代的必备工具:Webpack详解,为你的项目注入新活力

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一…

sentinel规则持久化-规则同步nacos-最标准配置

官方参考文档&#xff1a; 动态规则扩展 alibaba/Sentinel Wiki GitHub 需要修改的代码如下&#xff1a; 为了便于后续版本集成nacos&#xff0c;简单讲一下集成思路 1.更改pom 修改sentinel-datasource-nacos的范围 将 <dependency><groupId>com.alibaba.c…

Redis快速上手篇七(集群-六台虚拟机)

Redis集群 主从复制的场景无法吗满足主机单点故障时需要引入集群配置 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服务器主要用来处理写请求&#xff0c;部署多台从服务器 &#…

C++中的std::cout与std::cerr、std::clog

本文用于记录C中std::cout与std::cerr、std::clog的异同 std::cerr 是C标准库中的标准错误输出流&#xff0c;用于向标准错误设备输出信息&#xff0c;通常用于报告程序的错误和异常情况。与之相对的&#xff0c;std::cout 是标准输出流&#xff0c;用于向标准输出设备输出一般…

金属压铸件自动化3D全尺寸测量设备自动外观检测三维检测-CASAIM

铸造作为现代装备制造工业的基础共性技术之一&#xff0c;铸件产品既是工业制造产品&#xff0c;也是大型机械的重要组成部分&#xff0c;被广泛运用在航空航天、工业船舶、机械电子和交通运输等行业。 铸件形状复杂&#xff0c;一般的三坐标或者卡尺圆规等工具难以获取多特征…

蓝牙 - BLE SPP实现举例 (Bluecode Protocol Stack)

这里以一个无线扫描枪设备为例&#xff0c;这个设备会通过蓝牙通讯协议连接一个底座&#xff0c;使用的是BLE SPP进行通讯。 扫描枪用来扫条码&#xff0c;解析出条码信息后&#xff0c;将数据通过无线传输给底座&#xff0c;底座再通过USB将数据传送给电脑。 底座是Central d…

C语言KR圣经笔记 2.8自增和自减 2.9位运算 2.10赋值

2.8 自增和自减操作符 C提供了两个不同寻常的操作符&#xff0c;用于对变量进行自增和自减。自增操作符对操作数加上1&#xff0c;而自减操作符 -- 对操作数减去1。我们已经频繁使用 对变量进行自增&#xff0c;如&#xff1a; if (c \n)nl; 不寻常之处在于 和 -- 既能用作…

如何将 ONLYOFFICE 桌面版编辑器 7.5 安装到 Red Hat、CentOS 及衍生产品上

使用桌面版的 ONLYOFFICE 在线编辑器&#xff0c;您可使用本地文件操作&#xff0c;无需保持互联网连接状态。 ONLYOFFICE 桌面编辑器是什么 ONLYOFFICE 桌面编辑器是一款全面的办公工具&#xff0c;提供了文本文档、电子表格、演示文稿、可填写表单和 PDF 查看和编辑功能。它…

百度富文本上传图片后样式崩塌

&#x1f525;博客主页&#xff1a; 破浪前进 &#x1f516;系列专栏&#xff1a; Vue、React、PHP ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 问题描述&#xff1a;上传图片后&#xff0c;图片会变得很大&#xff0c;当点击的时候更是会顶开整个的容器的高跟宽 原因&#…

mac 安装homebrew ,golang

mac 安装homebrew ,golang 安装homebrew安装golang选择 apple arm 版本安装配置环境变量 安装homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"回车执行指令后&#xff0c;根据提示操作。具体包括以下提示操作&am…

CXL技术交流群问题讨论记录(1)

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c;转载或引用请注明出处【https://mangopapa.blog.csdn.net/article/details/134131924】。…

Vue 的双向数据绑定是如何实现的?

目录 1. 响应式数据 2. v-model 指令 3. 实现原理 4. 总结 Vue.js 是一款流行的前端 JavaScript 框架&#xff0c;它以其强大的双向数据绑定能力而闻名。双向数据绑定使得数据在视图和模型之间保持同步&#xff0c;并且任一方的变化都会自动反映到另一方。那么&#xff0c;…