Server-sent events(SSE) EventSource 客户端使用与服务器基础实现(基于Node.js)
文章目录
- 目的
- 基础说明
- 客户端使用
- 服务器实现
- 注意事项
- 总结
目的
传统的Web前后台通讯主要是使用HTTP方式进行的,通常是前台需要什么就主动向后台请求,后台无法直接向前台发送数据。通常后台数据如果频繁变动的话前台主要靠 轮询 或是 长连接 方式来处理,两种方式相对来说都不是很优雅。
而到了现在有两种方案来处理这个问题: WebSocket 和 Server-sent events(SSE) 。 WebSocket 可以实现实时的双向通讯,功能上来说是非常强的,不过相对于HTTP而言是一种另起炉灶的技术。Server-sent events 则是在HTTP之上扩展出来的功能,有点像前面提到的 长连接 ,但是这是原生的标准,功能上更加完善,使用起来也更加方便。这篇文章将对 Server-sent events 相关内容做个说明。
基础说明
Server-sent events 是H5中加入的功能,它是在HTTP上扩展出来的功能,使得服务器可以主动发送数据给客户端。在客户端使用 EventSource 接口来处理 Server-sent events 。
Server-sent events 最核心的其实就是新增了一个 MIME type : text/event-stream
。看名字就是知道这是一个流,只要不结束的的话就一直可以传数据。
实际使用中只要客户端主动发起访问接口,建立连接后就不用管了,服务器会在需要的时候主动推送消息。
Server-sent events 这种原生的功能有一个好处是浏览器端默认会自动重连。
客户端使用
客户端使用 EventSource 接口来处理 Server-sent events 。使用方法主要如下:
var es = new EventSource("/sse"); // 声明EventSource对象并连接urles.onmessage = (e) => {} // 收到服务器消息时触发es.onopen = (e) => {} // 连接建立时触发es.onerror = (e) => {} // 发生错误时触发// es.close(); // 关闭EventSource连接// console.log(es.url); // console.log(es.readyState); // 连接状态: 0 - connecting; 1 - open; 2 - closed;
客户端基本的使用是比较简单的,演示需要结合下面服务器进行。
对于前端来说直接使用JS的EventSource接口就可以使用SSE了,对于其它语言作为客户端来说可能没有现成的方法可用,但其实要用上也挺简单,使用 GET
方法访问链接,并在头文件中包含下面属性即可(只是建议,并不是必须):
accept: text/event-stream
cache-control: no-store
connection: keep-alive
这样就可以建立起连接了,之后等待并处理来自服务器的数据就行。
服务器实现
Server-sent events 是在HTTP上扩展出来的功能,所以服务器实现只需要在HTTP服务器的基础上稍作处理即可,最主要的就是设置响应头中 MIME type 为 text/event-stream
。下面是个最简单的例子:
const http = require('http')const server = http.createServer((req, res) => {// 访问链接 /sseif (req.url == '/sse') {res.writeHead(200, {"Content-Type": "text/event-stream","Cache-Control": "no-cache","Connection": "keep-alive",});res.write("data: " + 'connected' + "\n\n");// 服务器定期向客户端主动发消息interval = setInterval(function () { res.write("data: " + 'hello world' + "\n\n");}, 5000);// req.on('close', () => {}) // 客户端断开连接时触发return}// 其它任何链接都返回网页res.statusCode = 200res.end(`<script>var es = new EventSource("/sse");es.onmessage = (e) => { console.log(e); }es.onopen = (e) => { console.log(e); }es.onerror = (e) => { console.log(e); }</script>`)
})server.listen(80, '127.0.0.1', () => {console.log(`Server running at http://127.0.0.1/`)
})
上面例子中服务器在收到EventSource的连接请求后返回了 200
状态码,并在响应头中加入了 text/event-stream
,这些内容发送给客户端后连接就算建立完成了。之后只要有需要时服务器再向客户端发送消息即可,上面例子中使用定时器来模拟发送消息。
Server-sent events中服务器发送的数据必须是 UTF-8 编码的文本,还有一定的格式要求:
- 数据必须是一段一段发送,每端之间必须有空行
比如上面例子中的\n\n
,后一个换行符就提供 了空行 - 数据前有特定的标识字段
比如上面例子中发送消息使用data: 数据文本
上面提到的标识字段可选值如下:
data:
event:
定义事件类型,未设置此项的情况下发送数据会触发 message 事件,即默认的 onmessage 方法;id:
标识当前这段信息用的编号,客户端可以通过 lastEventId 属性来获取,如果连接断开,客户端在建立重连的时候会在请求头中的 Last-Event-ID 字段中填写最近的 id ;retry:
指定浏览器重新发起连接的时间间隔;:
会被忽略的信息,网络中的服务器可能会关闭长时间(比如15秒)未传输数据的连接,可以使用该方式发送消息来保持连接;
针对上面的一些内容可以使用下面方式进行测试:
const http = require('http')const server = http.createServer((req, res) => {// 访问链接 /sseif (req.url == '/sse') {console.log(req.headers);res.writeHead(200, {"Content-Type": "text/event-stream","Cache-Control": "no-cache","Connection": "keep-alive",});res.write("retry: 10000\n");res.write("event: connected\n");res.write("data: connected\n\n");// 服务器定期向客户端主动发消息interval = setInterval(function () { res.write("data: " + "hello world" + "\n");res.write("id: " + "aaa" + "\n\n");res.write("event: " + "naisu" + "\n");res.write("data: " + "233~~~" + "\n\n");}, 5000);return}// 其它任何链接都返回网页res.statusCode = 200res.end(`<script>var es = new EventSource("/sse");es.onmessage = (e) => { console.log(e); } // 使用data取数据es.addEventListener("connected", (e) => { console.log(e) }, false); // 监听自定义的事件es.addEventListener("naisu", (e) => { console.log(e) }, false); // 监听自定义的事件</script>`)
})server.listen(80, '127.0.0.1', () => {console.log(`Server running at http://127.0.0.1/`)
})
注意事项
Server-sent events 虽然简单,但使用时还有一些事项需要注意:
- 浏览器连接数量限制
大多数浏览器对于同一个IP或域名都有连接数量限制(比如chrome上限是6个),对于普通的HTTP请求,连接一下又断开了这没什么问题,但 Server-sent events 是长连接,超过6个就无法再连接了; - 长时间未传输数据连接被关闭
真实环境中数据传输过程中可能会经过代理服务器等网络节点,这些节点可能会关闭长时间未传输数据的连接; - 数据不实时传输
真实环境中数据传输过程中可能会经过代理服务器等网络节点,这些节点可能会缓存数据,达到一定数量后才转发,可以关闭相关缓存以提高实时性;
总结
Server-sent events的使用总的来说挺简单的,更多内容可以参考下面链接:
https://html.spec.whatwg.org/multipage/server-sent-events.html
http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html
Server-sent events(SSE) EventSource 客户端使用与服务器基础实现(基于Node.js)相关推荐
- 基于node.js的ws模块和net模块实现的浏览器与tcp客户端实时通讯小例程
适用于物联网设备的接入,网页端实时监控终端数据的场景 项目运行 测试通讯 功能描述 项目运行 项目地址:tcp-ws 下载之后进入文件夹,控制台执行npm install安装依赖包. 安装完毕后npm ...
- js ftpclient linux server,Node.JS用Socket实现FTP Server服务器和Client客户端
通信过程 FTP协议其实就是主机和服务通过Socket进行固定格式的通信过程,当某客户端连接到FTP 服务器后,客户端发送指令: [参数] 服务会按以下格式返回: [参数或说明] 例如以下是FileZ ...
- 微信小程序商城服务器搭建,基于微信小程序商城毕业设计(小程序客户端+服务端Node.js源码)毕业论文+运行说明...
微信小程序商城毕业设计(微信小程序客户端毕业设计) 摘 要 购物商城系统是保证以购物商城为基础的网上交易实现的体系.市场交易是由参与交易双方在平等.自由.互利的基础上进行的基于价值的交换.网上交易同 ...
- Exchange server 2013(十三)AD RMS客户端故障排除
Exchange server 2013(十三) AD RMS客户端故障排除 在windows server 2012上部署完RMS及一些基本的配置服务后,我们使用OWA发送(选择不转发)邮件正常,接 ...
- Windows Server 2022 开始,DNS 客户端支持 DNS over-HTTPS (DoH)
从 Windows Server 2022 开始,DNS 客户端支持 DNS over-HTTPS (DoH) . 启用 DoH 后,Windows服务器的 DNS 客户端和 DNS 服务器之间的 D ...
- SQL Server 2005 Express 远程连接 客户端 远程访问 设置 全攻略 (适用 SQL Server 2005 其他版本)
SQL Server 2005 Express 是微软提供的数据库的低端解决方案, 可免费任意随产品分发, 可以在XP等非专业服务器系统下安装, 还可以远程访问, 对于小型数据应用程序已足够满足数据使 ...
- 逐句回答,流式返回,ChatGPT采用的Server-sent events后端实时推送协议Python3.10实现,基于Tornado6.1
善于观察的朋友一定会敏锐地发现ChatGPT网页端是逐句给出问题答案的,同样,ChatGPT后台Api接口请求中,如果将Stream参数设置为True后,Api接口也可以实现和ChatGPT网页端一样 ...
- 来自网页的消息服务器繁处理忙,EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新...
//--------------------------------客户端代码----------------------------- if(typeof(EventSource) !== &quo ...
- mysql客户端不支持_MySQL 8.0 - 客户端不支持服务器请求的身份验证协议; 考虑升级MySQL客户端...
MySQL 8.0 - 客户端不支持服务器请求的身份验证协议; 考虑升级MySQL客户端 我是node.js和MySQL初学者,我刚开始设置并尝试一些基本代码.但是,由于某种原因,我甚至无法与服务器建 ...
- 初涉SQL Server性能问题(1/4):服务器概况
原文:初涉SQL Server性能问题(1/4):服务器概况 当你作为DBA时,很多人会向你抱怨:"这个程序数据加载和蜗牛一样,你看看是不是服务器出问题了?"造成这个问题的原因有很 ...
最新文章
- Eclipse中配置约束
- 虚拟化基础架构Windows 2008篇之1-虚拟化基础服务概述
- 登录页面和FORM的职责不对称,处理方法,刷新工作流程
- myeclipse 重新关联项目和svn
- css练习题4,复习webpack4之CSS文件代码分割
- Java 动态加载类
- (后端)Java中关于金额大小写的工具类
- UI设计师收好!哪些会说故事的插画素材!
- 单选框_flutter Radio 单选框
- 数字图像处理——图像的统计特征
- RX.AutoImage+Fluent Airpak v2.1
- vbs整人代码,表白+提醒 两段代码就OK
- 用ViewPager实现微信tab切换
- win10系统pyCharm安装及最新2018激活码
- CentOS上如何顺利地安装MySQL?
- c270 linux驱动下载,佳能 HD Webcam C270 驱动程序下载-更新佳能软件(网络摄像头)
- 大学生了没-20120709迅雷下载
- 如何增长U盘的寿命- 小技巧
- ParaView绘制自由水面的等值线图
- java命名规范(驼峰命名法)
热门文章
- 团队博客-应用功能说明书
- 寒假第二周 总结与反思
- python化学公式配平_配平化学方程式的C++代码实现
- 古诗词学习-归园田居+牧童+凉州词·其一+马诗+逢雪宿芙蓉山主人+凉州词+别董大+枫桥夜泊+滁州西涧+渔歌子+塞下曲
- matlab如何算排列组合数,MATLAB 排列组合问题
- 求解逆矩阵的常用三种方法
- java 连续数字_java 如何判断数字是否连续?求大神解答
- 《团队-科学计算器-项目总结》
- 计算机证书都需要哪些知识,计算机资格证书有哪些计算机专业证书有哪些
- firewalld系列一:自定义zone与ipset