你还在使用websocket实现实时消息推送吗?
前言
服务端向客户端推送数据的实现方案有哪几种?
-
轮询 -
websocket -
SSE
轮询简介
-
首先轮询需要不断的发起请求,每一个请求都需要经过http建立连接的流程(比如三次握手,四次挥手),是没有必要的消耗。 -
客户端需要从页面被打开的那一刻开始就一直处理请求。虽然每次轮询的消耗不大,但是一直处理请求对于客户端来说一定是不友好的。 -
浏览器请求并发是有限制的。比如Chrome 最大并发请求数目为 6,这个限制还有一个前提是针对同一域名的,超过这一限制的后续请求将会被阻塞。而轮询意味着会有一个请求长时间的占用并发名额。 -
而如果轮询时间较长,可能又没有办法非常及时的获取数据
websocket简介
SSE简介
websocket和SSE有什么区别?
轮询
Websocket和SSE
-
WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。 -
WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。 -
SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。 -
SSE默认支持断线重连,WebSocket则需要额外部署。 -
SSE支持自定义发送的数据类型。
Websocket和SSE分别适用于什么业务场景?
SSE有哪些主要的API?
SSE连接状态
-
0,相当于常量EventSource.CONNECTING,表示连接还未建立,或者连接断线。 -
1,相当于常量EventSource.OPEN,表示连接已经建立,可以接受数据。 -
2,相当于常量EventSource.CLOSED,表示连接已断,且不会重连。
SSE相关事件
-
open事件(连接一旦建立,就会触发open事件,可以定义相应的回调函数) -
message事件(收到数据就会触发message事件) -
error事件(如果发生通信错误(比如连接中断),就会触发error事件)
数据格式
Content-Type: text/event-stream //文本返回格式 Cache-Control: no-cache //不要缓存 Connection: keep-alive //长链接标识
如何实操一个SSE链接?Demo↓
-
第一步,建立一个index.html文件,然后复制前端代码Demo到index.html文件中,打开文件 -
第二步,进入一个新的文件夹,建立一个index.js文件,然后将后端Demo代码复制进去,然后在该文件夹下执行
npm init //初始化npm npm i express //下载node express框架 node index //启动服务
前端代码Demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <ul id="ul"> </ul> </body> <script> //生成li元素 function createLi(data){ let li = document.createElement("li"); li.innerHTML = String(data.message); return li; } //判断当前浏览器是否支持SSE let source = '' if (!!window.EventSource) { source = new EventSource('http://localhost:8088/sse/'); }else{ throw new Error("当前浏览器不支持SSE") } //对于建立链接的监听 source.onopen = function(event) { console.log(source.readyState); console.log("长连接打开"); }; //对服务端消息的监听 source.onmessage = function(event) { console.log(JSON.parse(event.data)); console.log("收到长连接信息"); let li = createLi(JSON.parse(event.data)); document.getElementById("ul").appendChild(li) }; //对断开链接的监听 source.onerror = function(event) { console.log(source.readyState); console.log("长连接中断"); }; </script> </html>
后端代码Demo(node的express)
const express = require('express'); //引用框架 const app = express(); //创建服务 const port = 8088; //项目启动端口 //设置跨域访问 app.all("*", function(req, res, next) { //设置允许跨域的域名,*代表允许任意域名跨域 res.header("Access-Control-Allow-Origin", '*'); //允许的header类型 res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With"); //跨域允许的请求方式 res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); // 可以带cookies res.header("Access-Control-Allow-Credentials", true); if (req.method == 'OPTIONS') { res.sendStatus(200); } else { next(); } }) app.get("/sse",(req,res) => { res.set({ 'Content-Type': 'text/event-stream', //设定数据类型 'Cache-Control': 'no-cache',// 长链接拒绝缓存 'Connection': 'keep-alive' //设置长链接 }); console.log("进入到长连接了") //持续返回数据 setInterval(() => { console.log("正在持续返回数据中ing") const data = { message: `Current time is ${new Date().toLocaleTimeString()}` }; res.write(`data: ${JSON.stringify(data)}\n\n`); }, 1000); }) //创建项目 app.listen(port, () => { console.log(`项目启动成功-http://localhost:${port}`) })
效果
总结
-
SSE比websocket更轻 -
SSE是基于http/https协议的 -
websocket是一个新的协议,ws/wss协议 -
如果只需要服务端向客户端推送消息,推荐使用SSE -
如果需要服务端和客户端双向推送,请选择websocket -
不论是SSE还是websocket,对于浏览器的兼容性都不错 -
轮询是下策,很占用客户端资源,不建议使用。(不过偷懒的时候他确实方便) -
IE不支持SSE -
小白同学demo如果跑不明白可以私信我
微信赞赏支付宝扫码领红包
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。侵权投诉:375170667@qq.com