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();
}
}
}