Skip to content

SSE简介

SSE是Server-Sent-Events的简称,SSE与websocket作用相似,都可以服务器向浏览器推送信息。

SSE优点

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

SSE客户端

SSE客户端API的EventSource对象中

js
if('EventSource' in window)
{
    //创建连接
    let url='/sse'
    //sse可跨域,参数withCredentials表示是否一起发送Cookie
    var source = new EventSource(url, { withCredentials: true });
    source.onopen=function(event){
        
    }
    source.onmessage=function(event){
        var data=event.data
        //your code
    }
    source.onerror=function(err){
        
    }
    //连接状态
    //source.readyState  0表示连接还未建立,或者断线正在重连 1表示连接已经建立,可以接受数据 2表示连接已断,且不会重连
    //关闭连接
    //source.close();
}

typescript

typescript
const url = 'https://localhost:7255/sse';
const sse = new EventSource(url);

sse.addEventListener('message', ({ data }) => {
    const d = JSON.parse(data);
    console.log(data);
});

sse.addEventListener('error', (err: any) => {
    console.log(err);
});

asp.net中使用SSE

使用库 Lib.AspNetCore.ServerSentEvents 实现

csharp
//添加sse服务
builder.Services.AddServerSentEvents();

//添加sse中间件
app.MapServerSentEvents("/sse");

或者

csharp
internal interface INotificationsServerSentEventsService : IServerSentEventsService
{ }

internal class NotificationsServerSentEventsService : ServerSentEventsService, INotificationsServerSentEventsService
{
    public NotificationsServerSentEventsService(IOptions<ServerSentEventsServiceOptions<NotificationsServerSentEventsService>> options)
        : base(options.ToBaseServerSentEventsServiceOptions())
    { }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...

        services.AddServerSentEvents();
        services.AddServerSentEvents<INotificationsServerSentEventsService, NotificationsServerSentEventsService>();

        ...
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        ...
        app.MapServerSentEvents("/default-sse-endpoint");
        app.MapServerSentEvents<NotificationsServerSentEventsService>("/notifications-sse-endpoint");

        ...
    }
}

发送消息

csharp
var data =new
{
	name="test"
};
await _serverSentEventsService.SendEventAsync(JsonSerializer.Serialize(data));

给指定客户端发消息

csharp
public class CookieBasedServerSentEventsClientIdProvider : IServerSentEventsClientIdProvider
{
	private const string COOKIE_NAME = ".ServerSentEvents.Guid";

	public Guid AcquireClientId(HttpContext context)
	{
		Guid clientId;
		string cookieValue = context.Request.Cookies[COOKIE_NAME];
		if (String.IsNullOrWhiteSpace(cookieValue) || !Guid.TryParse(cookieValue, out clientId))
		{
			clientId = Guid.NewGuid();
			context.Response.Cookies.Append(COOKIE_NAME, clientId.ToString());
		}
		return clientId;
	}

	public void ReleaseClientId(Guid clientId, HttpContext context)
	{
        try	{context.Response.Cookies.Delete(COOKIE_NAME);}catch{}
	}
}
csharp
builder.Services.AddServerSentEventsClientIdProvider<CookieBasedServerSentEventsClientIdProvider>();

 public class WeatherForecastController : ControllerBase
 {
     IServerSentEventsService _serverSentEventsService;
	 IServerSentEventsClientIdProvider serverSentEventsClientIdProvider;
     public WeatherForecastController(IServerSentEventsService serverSentEventsService,IServerSentEventsClientIdProvider serverSentEventsClientIdProvider)
    {
        _serverSentEventsService = serverSentEventsService;
        this.serverSentEventsClientIdProvider = serverSentEventsClientIdProvider;
    }
     
    [HttpGet("test2")]
    public async Task test2()
    {
        //获取当前客户端
        var id = serverSentEventsClientIdProvider.AcquireClientId(HttpContext);
        //向指定客户端发消息
         var data =new
        {
            name="test"
        };
        var msg=JsonSerializer.Serialize(data);
        await _serverSentEventsService.SendEventAsync(msg,x=>x.Id==id);

        //关闭客户端连接
        var client = _serverSentEventsService.GetClient(id);
        await client.DisconnectAsync();
        }
     }
}

查看更多SSE API文档