SSE的使用

SSE的使用

前提需求

web开发过程中需要前后端进行实时数据或者定时数据推送的需求中,常见的解决方案就是长轮询,段轮询,sse和websockt。

长轮询与段轮询都是通过定时的http请求实现,弊端都是需要多次向服务器发起http请求。

sse和websockt都能实现一次请求多次传输,可以简单的理解为sse为单工通信,websocket是双工通信(虽然这样并不完全准确)

SSE简介

严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming)。

也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。

SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。

SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。

总体来说,WebSocket 更强大和灵活。因为它是全双工通道,可以双向通信;SSE 是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。如果浏览器向服务器发送信息,就变成了另一次 HTTP 请求。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是,SSE 也有自己的优点。

  • SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
  • SSE 属于轻量级,使用简单;WebSocket 协议相对复杂。
  • SSE 默认支持断线重连,WebSocket 需要自己实现。
  • SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
  • SSE 支持自定义发送的消息类型。

因此,两者各有特点,适合不同的场合。

使用demo

客户端(HTML)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script lang="javascript">
        function sse() {
            if (!('EventSource' in window)) {
                alert("不支持 EventSource");
                return;
            }

            let source = new EventSource("/api/sse");

            source.onopen = function (event) {
                console.log(event);
                console.log("onopen触发");
            };

            source.onmessage = function (event) {
                var data = event.data;
                console.log(data);
            };

            source.onerror = function (event) {
                console.log(event);
                console.log("onerror触发");
            };
            source.addEventListener("close", event => {
                source.close();
                console.log(event);
                console.log("close触发");
            });
        }

        window.onload = (s) => {
            sse();
        }
    </script>
</head>
<body>
    <div id="content"></div>
</body>
</html>

服务端

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace SSE服务端推送demo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SseController : ControllerBase
    {
        [HttpGet]
        public async Task Get()
        {
            Response.Headers.ContentType = "text/event-stream";
            Response.Headers.CacheControl = "no-cache";
            Response.Headers.Connection = "keep-alive";
            await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Response.WriteAsync(
                        $"data:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\n\n");
                    Task.Delay(1000).Wait();
                }

                Response.WriteAsync(
                    $"event:close\ndata:nothing\n\n");
            });

        }
    }
}

SSE API

在这里看吧 https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events

常用方法:

  • open 打开连接

  • close 关闭连接

事件:

  • onopen: 当打开时触发

  • onerror:当错误时触发

  • onmessage:当收到消息是触发

自定义关联事件:

  sse实例.addEventListener("xxxxx", event => {
               
            });

服务端数据处理

数据格式

event:xxxx\n
data:xxxxxxxx\n
id:xxxxx\n
retry:xxxxx\n\n

以上格式是一个完整的信息。

其中event可以省略,默认值是message

一条信息的最后一定是换两行,也就是两个\n\n

一下是一个c#的demo

  Response.WriteAsync(
                        $"data:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\n\n");

//发送自定义事件
 Response.WriteAsync(
                    $"event:close\ndata:nothing\n\n");

https://www.ruanyifeng.com/blog/2017/05/server-sent_events.html

https://developer.mozilla.org/zh-CN/docs/Web/API/Server-sent_events/Using_server-sent_events

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值