文章目录

  • 目的
  • 基础说明
  • 客户端使用
  • 服务器实现
  • 注意事项
  • 总结

目的

传统的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)相关推荐

  1. 基于node.js的ws模块和net模块实现的浏览器与tcp客户端实时通讯小例程

    适用于物联网设备的接入,网页端实时监控终端数据的场景 项目运行 测试通讯 功能描述 项目运行 项目地址:tcp-ws 下载之后进入文件夹,控制台执行npm install安装依赖包. 安装完毕后npm ...

  2. js ftpclient linux server,Node.JS用Socket实现FTP Server服务器和Client客户端

    通信过程 FTP协议其实就是主机和服务通过Socket进行固定格式的通信过程,当某客户端连接到FTP 服务器后,客户端发送指令: [参数] 服务会按以下格式返回: [参数或说明] 例如以下是FileZ ...

  3. 微信小程序商城服务器搭建,基于微信小程序商城毕业设计(小程序客户端+服务端Node.js源码)毕业论文+运行说明...

    微信小程序商城毕业设计(微信小程序客户端毕业设计) 摘  要 购物商城系统是保证以购物商城为基础的网上交易实现的体系.市场交易是由参与交易双方在平等.自由.互利的基础上进行的基于价值的交换.网上交易同 ...

  4. Exchange server 2013(十三)AD RMS客户端故障排除

    Exchange server 2013(十三) AD RMS客户端故障排除 在windows server 2012上部署完RMS及一些基本的配置服务后,我们使用OWA发送(选择不转发)邮件正常,接 ...

  5. Windows Server 2022 开始,DNS 客户端支持 DNS over-HTTPS (DoH)

    从 Windows Server 2022 开始,DNS 客户端支持 DNS over-HTTPS (DoH) . 启用 DoH 后,Windows服务器的 DNS 客户端和 DNS 服务器之间的 D ...

  6. SQL Server 2005 Express 远程连接 客户端 远程访问 设置 全攻略 (适用 SQL Server 2005 其他版本)

    SQL Server 2005 Express 是微软提供的数据库的低端解决方案, 可免费任意随产品分发, 可以在XP等非专业服务器系统下安装, 还可以远程访问, 对于小型数据应用程序已足够满足数据使 ...

  7. 逐句回答,流式返回,ChatGPT采用的Server-sent events后端实时推送协议Python3.10实现,基于Tornado6.1

    善于观察的朋友一定会敏锐地发现ChatGPT网页端是逐句给出问题答案的,同样,ChatGPT后台Api接口请求中,如果将Stream参数设置为True后,Api接口也可以实现和ChatGPT网页端一样 ...

  8. 来自网页的消息服务器繁处理忙,EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新...

    //--------------------------------客户端代码----------------------------- if(typeof(EventSource) !== &quo ...

  9. mysql客户端不支持_MySQL 8.0 - 客户端不支持服务器请求的身份验证协议; 考虑升级MySQL客户端...

    MySQL 8.0 - 客户端不支持服务器请求的身份验证协议; 考虑升级MySQL客户端 我是node.js和MySQL初学者,我刚开始设置并尝试一些基本代码.但是,由于某种原因,我甚至无法与服务器建 ...

  10. 初涉SQL Server性能问题(1/4):服务器概况

    原文:初涉SQL Server性能问题(1/4):服务器概况 当你作为DBA时,很多人会向你抱怨:"这个程序数据加载和蜗牛一样,你看看是不是服务器出问题了?"造成这个问题的原因有很 ...

最新文章

  1. Eclipse中配置约束
  2. 虚拟化基础架构Windows 2008篇之1-虚拟化基础服务概述
  3. 登录页面和FORM的职责不对称,处理方法,刷新工作流程
  4. myeclipse 重新关联项目和svn
  5. css练习题4,复习webpack4之CSS文件代码分割
  6. Java 动态加载类
  7. (后端)Java中关于金额大小写的工具类
  8. UI设计师收好!哪些会说故事的插画素材!
  9. 单选框_flutter Radio 单选框
  10. 数字图像处理——图像的统计特征
  11. RX.AutoImage+Fluent Airpak v2.1
  12. vbs整人代码,表白+提醒 两段代码就OK
  13. 用ViewPager实现微信tab切换
  14. win10系统pyCharm安装及最新2018激活码
  15. CentOS上如何顺利地安装MySQL?
  16. c270 linux驱动下载,佳能 HD Webcam C270 驱动程序下载-更新佳能软件(网络摄像头)
  17. 大学生了没-20120709迅雷下载
  18. 如何增长U盘的寿命- 小技巧
  19. ParaView绘制自由水面的等值线图
  20. java命名规范(驼峰命名法)

热门文章

  1. 团队博客-应用功能说明书
  2. 寒假第二周 总结与反思
  3. python化学公式配平_配平化学方程式的C++代码实现
  4. 古诗词学习-归园田居+牧童+凉州词·其一+马诗+逢雪宿芙蓉山主人+凉州词+别董大+枫桥夜泊+滁州西涧+渔歌子+塞下曲
  5. matlab如何算排列组合数,MATLAB 排列组合问题
  6. 求解逆矩阵的常用三种方法
  7. java 连续数字_java 如何判断数字是否连续?求大神解答
  8. 《团队-科学计算器-项目总结》
  9. 计算机证书都需要哪些知识,计算机资格证书有哪些计算机专业证书有哪些
  10. firewalld系列一:自定义zone与ipset