Web实时通讯的学习之旅:SSE(Server-Sent Events)的技术详解及简单示例演 ...

打印 上一主题 下一主题

主题 950|帖子 950|积分 2850

文章目次







      • 一、什么是SSE
      • 二、SSE技术的基本原理
      • 三、SSE适用于场景
      • 四、Node服务端示例


        • 1、协议
        • 2、格式
        • 3、事件


          • 3.1、事件
          • 3.2、事件唯一标识符
          • 3.3、重连事件

        • 4、具体示例

      • 五、客户端示例


        • 1、检测客户端是否支持SSE
        • 2、创建客户端毗连
        • 3、事件监听
        • 4、吸收事件
        • 5、自界说事件
        • 6、错误处置惩罚
        • 7、自动断开毗连
        • 8、具体示例

      • 六、注意事项


        • 1、nginx配置
        • 2、EventSource



一、什么是SSE

服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE)。
SSE(Server-Sent Events)是一种用于实现服务器自动向客户端推送数据的技术,也被称为“事件流”(Event Stream)。它基于 HTTP 协议,利用了其长毗连特性,在客户端与服务器之间建立一条长期化毗连,并通过这条毗连实现服务器向客户端的实时数据推送。
SSE 是HTML5规范的一部分,该规范非常简单,主要由两部分组成:第一部分是服务端与浏览器端的通讯协议(Http协议),第二部分是浏览器端可供JavaScript利用的EventSource对象。
严格意义上来说,Http协议是无法做到服务器自动想浏览器发送协议,但是可以变通下,服务器向客户端发起一个声明,我下面发送的内容将是 text/event-stream 格式的,这个时间浏览器就知道了。响应文本内容是一个持续的数据流,每个数据流由差别的事件组成,并且每个事件可以有一个可选的标识符,差别事件内容之间只能通过回车符 和换行符 来分隔,每个事件可以由多行组成。目前除了IE和Edge,其他浏览器均支持。
二、SSE技术的基本原理

客户端向服务器发送一个GET请求,带有指定的header,表示可以吸收事件流类型,并禁用任何的事件缓存。
服务器返回一个响应,带有指定的header,表示事件的媒体类型和编码,以及利用分块传输编码(chunked)来流式传输动态生成的内容。
服务器在有数据更新时,向客户端发送一个或多个名称:值字段组成的事件,由单个换行符分隔。事件之间由两个换行符分隔。服务器可以发送事件数据、事件类型、事件ID和重试时间等字段。
客户端利用EventSource接口来创建一个对象,打开毗连,并订阅onopen、onmessage和onerror等事件处置惩罚程序来处置惩罚毗连状态和吸收消息。
客户端可以利用GET查询参数来通报数据给服务器,也可以利用close方法来关闭毗连。
三、SSE适用于场景

SSE适用场景是指服务器向客户端实时推送数据的场景,比方:


  • 股票价格更新:服务器可以根据股市的变化,实时地将股票价格推送给客户端,让客户端可以或许及时了解股票的走势和行情。
  • 新闻实时推送:服务器可以根据新闻的更新,实时地将新闻内容或标题推送给客户端,让客户端可以或许及时了解最新的新闻动态和信息。
  • 在线聊天:服务器可以根据用户的发送,实时地将聊天消息推送给客户端,让客户端可以或许及时收到和回复消息。
  • 实时监控:服务器可以根据设备的状态,实时地将监控数据或报警信息推送给客户端,让客户端可以或许及时了解设备的运行环境和非常环境。
SSE适用场景的特点是:


  • 数据更新频仍:服务器必要不停地将最新的数据推送给客户端,保持数据的实时性和正确性。
  • 低延迟:服务器必要尽快地将数据推送给客户端,避免数据的延迟和过期。
  • 单向通讯:服务器只必要向客户端推送数据,而不必要吸收客户端的数据。
chatGPT 返回的数据 就是利用的SSE 技术
实时数据大屏 假如只是必要展示 实时的数据可以利用SSE技术 而不黑白要利用webSocket
四、Node服务端示例

EventSource这个api是一个用于吸收服务器发送事件(Server-Sent Events,SSE)的Web API接口。服务器发送事件是一种让服务器端可以或许自动向客户端发送数据的技术,它利用HTTP协议,并且遵照一定的格式。
1、协议

SSE 协议非常简单,正常的Http请求,更改请起头相关配置即可
  1. Content-Type: text/event-stream,utf-8
  2. Cache-Control: no-cache
  3. Connection: keep-alive
复制代码
2、格式

文本流基础格式如下,以行为单位的,以冒号分割 Field 和 Value,每行结尾为 ,每行会Trim掉前后空字符,因此 也可以。
每一次发送的信息,由多少个message组成,每个message之间用 分隔。每个message内部由多少行组成,每一行都是如下格式。
  1. field: value
  2. field: value
复制代码
Field是有5个固定的name
  1. data     // 数据内容
  2. event    // 事件
  3. id       // 数据标识符用id字段表示,相当于每一条数据的编号
  4. retry    // 重试,服务器可以用retry字段,指定浏览器重新发起连接的时间间隔
  5. :        //冒号开头是比较特殊的,表示注释
复制代码
3、事件

每个事件之间通过空行来分隔。对于每一行来说,冒号(“:”)前面表示的是该行的类型,冒号后面则是对应的值。可能的类型包括:


  • 类型为空白,表示该行是解释,会在处置惩罚时被忽略。
  • 类型为 data,表示该行包含的是数据。以 data 开头的行可以出现多次。全部这些行都是该事件的数据。
  • 类型为 event,表示该行用来声明事件的类型。浏览器在收到数据时,会产生对应类型的事件。
  • 类型为 id,表示该行用来声明事件的标识符。
  • 类型为 retry,表示该行用来声明浏览器在毗连断开之后进行再次毗连之前的期待时间。
3.1、事件

事件之间用 隔断,一般一个事件一行,也可以多行
  1. # 一个事件一行
  2. data: message
  3. data: message2
  4. # 一个事件多行
  5. data: {
  6. data: "name": "zhangsan",
  7. data: "age", 25
  8. data: }
  9. # 自定义事件
  10. event: foo
  11.    // 自定义事件,名称 foo,触发客户端的foo监听事件
  12. data: a foo event
  13. // 内容
  14. data: an unnamed event
  15. // 默认事件,未指定事件名称,触发客户端 onmessage 事件
  16. event: bar
  17.    // 自定义时间,名称 bar,触发客户端bar监听事件
  18. data: a bar event
  19. // 内容
复制代码
3.2、事件唯一标识符

每个事件可以指定一个ID,浏览器会跟踪事件ID,假如发生了重连,浏览器会把近来吸收到的时间ID放到 HTTP Header Last-Event-ID 中,作为一种简单的同步机制。
  1. id: eef0128b-48b9-44f7-bbc6-9cc90d32ac4f
  2. data: message
复制代码
3.3、重连事件

制止毗连,客户端一般会3秒重连,但是服务端也可以配置
  1. retry: 10000
复制代码
4、具体示例

在Node.js中利用Server-Sent Events(SSE),你可以创建一个HTTP服务器,并利用res对象的write方法来向客户端发送长期的流信息。
  1. const http = require('http');
  2. const server = http.createServer((req, res) => {
  3.     // 对于SSE请求,需要设置正确的Content-Type和Cache-Control
  4.     // 设置Content-Type头为text/event-stream,这是SSE所需的。
  5.     // 设置Cache-Control头为no-cache,这将防止客户端缓存事件流。
  6.     // 使用Connection: keep-alive,这将保持连接打开,直到服务器明确地关闭连接。
  7.     res.writeHead(200, {
  8.         'Content-Type': 'text/event-stream',
  9.         'Cache-Control': 'no-cache',
  10.         'Connection': 'keep-alive',
  11.         'Access-Control-Allow-Credentials': true,
  12.         'Access-Control-Allow-Origin': '*'
  13.     });
  14.     // 每隔一定时间发送一次消息
  15.     // 使用res.write()方法将新的数据发送到客户端。
  16.     // 我们在数据前添加了data:前缀,这是SSE事件流所需的。
  17.     // 最后,我们在每个事件之间添加了一个空行
  18. ,这是SSE事件流规范要求的,以便客户端可以正确解析事件流
  19.     setInterval(() => {
  20.         const data = `data: ${new Date().toISOString()}
  21. `;
  22.         res.write(data);
  23.     }, 1000);
  24.     // 当客户端断开连接时,清理资源
  25.     req.on('close', () => {
  26.         clearInterval(); // 清除定时器
  27.         res.end(); // 结束响应
  28.     });
  29. });
  30. server.listen(3000, () => {
  31.     console.log('Server is running on port 3000');
  32. });
复制代码
我们创建了一个简单的HTTP服务器,监听3000端口。对于每个到来的请求,我们设置适当的响应头,并开始向客户端发送事件。我们利用setInterval每秒发送一个包含当前日期和时间的事件。当客户端断开毗连时,我们扫除定时器并竣事响应。如许,你就可以在Node.js中利用SSE向客户端推送实时数据了。
五、客户端示例

1、检测客户端是否支持SSE

  1. function supportsSSE() {
  2.   return !!window.EventSource;
  3. }
复制代码
2、创建客户端毗连

客户端实现就比较简单了,实例化一个EventSource对象,url 可以和服务端同域,也可以跨域,假如跨域的话,必要指定第二个参数withCredentials:true,表示发送Cookie到服务端
  1. //创建一个EventSource对象,用于从sse.php页面接收事件
  2. const evtSource = new EventSource("http://localhost:3000");
复制代码
3、事件监听

事件源毗连后会发送 “open” 事件,可以通过以下两种方式监听
  1. # 方式一:
  2. source.onopen = function(event) {
  3.   // handle open event
  4. };
  5. ## 方式二:
  6. source.addEventListener("open", function(event) {
  7.   // handle open event
  8. }, false);
复制代码
4、吸收事件

吸收事件同样和上面同样有两种方式。浏览器会自动把一个消息中的多个分段拼接成一个完整的字符串,因此,可以轻松地在这里利用 JSON 序列化和反序列化处置惩罚。
  1. # 方式一:
  2. source.onmessage = function(event) {
  3.   var data = event.data;
  4.   var lastEventId = event.lastEventId;
  5.   // handle message
  6. };
  7. ## 方式二:
  8. source.addEventListener("message", function(event) {
  9.   var data = event.data;
  10.   var lastEventId = event.lastEventId;
  11.   // handle message }, false);
复制代码
5、自界说事件

默认环境下,服务器发送过来的消息,都是默认事件格式的数据,这个时间都会触发onmessage,假如后端自界说事件的话,则不会触发onmessage,这个是否我们必要添加对应的监听事件
  1. source.addEventListener('foo', function (event) {
  2.   var data = event.data;
  3.   // handle message
  4. }, false);
复制代码
6、错误处置惩罚

  1. # 方式一:
  2. source.onerror = function(event) {
  3.   // handle error event
  4. };
  5. ## 方式二:
  6. source.addEventListener("error", function(event) {
  7.   // handle error event
  8. }, false);
复制代码
7、自动断开毗连

  1. source.close()
复制代码
8、具体示例

  1. // 先判断当前浏览器是否支持EventSource事件if (typeof(EventSource) !== "undefined") {  // 用JavaScript创建了一个新的EventSource对象,它将从服务器端的/test/server-sent-events路由吸收事件流  const source = new EventSource('/test/server-sent-events', {    withCredentials: true  });    每当服务器发送新的事件时,source.onmessage事件处置惩罚程序将运行,我们将事件数据剖析为JSON对象  source.onmessage = (event) => {     const data = JSON.parse(event.data)     console.log(data)  }    // close方法用于关闭 SSE 毗连。  source.close()
  2. ; } else {  console.log('不支持 EventSource')}
复制代码
六、注意事项

1、nginx配置



  • 利用nginx做反向署理时必要将proxy_buffering关闭
    proxy_buffering off
  • 大概加上响应头部x-accel-buffering,如许nginx就不会给后端响应数据加buffer
    x-accel-buffering: no
2、EventSource



  • 毗连关闭后会自动重连
  • 必要显示的调用close方法

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表