2.13Server-Sent Events 单向通信

随着人工智能聊天机器人 ChatGPT 的快速流行,其用户界面中模拟打字机效果的对话设计给人留下了深刻印象。这种生动逼真的交互体验,实际上是通过一种称为“服务器发送事件”(Server-Sent Events, SSE)的技术实现的。

随着人工智能聊天机器人 ChatGPT 的快速流行,其用户界面中模拟打字机效果的对话设计给人留下了深刻印象。这种生动逼真的交互体验,实际上是通过一种称为“服务器发送事件”(Server-Sent Events, SSE)的技术实现的。

Server-Sent Events 是一种允许服务器主动向客户端(通常是浏览器)发送实时更新数据的通信技术。与传统的客户端请求-服务器响应模式不同,SSE 实现了服务器到客户端的单向、异步通信,从而无需客户端不断轮询服务器以获取最新数据。 这种技术极大地减轻了服务器的负担,并提高了数据传输的效率和实时性。

Server-Sent Events 的应用场景:

  1. 实时通知:可以用来实现实时的消息提醒或通知系统,如社交网络上的新消息提示或邮件到达通知。
  2. 数据流更新:对于需要持续更新的数据,如股票价格、天气信息或体育比赛结果,SSE 能够提供即时的数据更新。
  3. 进度报告:在执行耗时较长的任务时,比如文件上传或复杂计算过程中,SSE 可以用来向客户端报告任务的进度。
  4. 日志和监控:在开发和运维领域,SSE 可用于实时显示日志文件的变化或监控系统的健康状态。

以下示例展示了如何使用 Server-Sent Events 向服务器获取数据:

cs
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events"   // 接收到数据时的操作   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }, cancellationToken: cancellationToken);// 使用构建器模式await httpRemoteService.SendAsync(HttpRequestBuilder   .ServerSentEvents("https://localhost:7044/HttpRemote/Events"   // 接收到数据时的操作   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }), cancellationToken: cancellationToken);

Server-Sent Events 也支持以 IAsyncEnumerable<ServerSentEventsData> 的方式消费数据,让你可以使用 await foreach 来迭代每个轮询响应:

cs
await foreach (var data in httpRemoteService.ServerSentEventsAsAsyncEnumerable("https://localhost:7044/HttpRemote/Events", cancellationToken: cancellationToken)){    Console.WriteLine(data.Data);}// 使用构建器模式await foreach (var data in httpRemoteService.SendAsAsyncEnumerable(HttpRequestBuilder.ServerSentEvents("https://localhost:7044/HttpRemote/Events"), cancellationToken)){    Console.WriteLine(data.Data);}

data 参数的类型为 ServerSentEventsData,包含以下属性:

  • 属性
    • Event:事件类型(string 类型)。
    • Data:消息(string 类型)。
    • RawLine:原始消息行(string 类型)。
    • Id:事件 IDstring 类型)。
    • Retry:重新连接的时间(以毫秒为单位的 int 类型)。
    • CustomFields:自定义的字段数据(IReadOnlyCollection<KeyValuePair<string, string>> 类型)。

您还可以监听连接成功和发送异常时的事件:

cs
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events"   // 接收到数据时的操作   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }, builder => builder   // 连接打开时操作   .SetOnOpen(() =>   {       Console.WriteLine("连接成功。");   })   // 连接未打开时操作   .SetOnError((ex) =>   {       Console.WriteLine("连接错误。" + ex.Message);   }), cancellationToken: cancellationToken);// 使用构建器模式await httpRemoteService.SendAsync(HttpRequestBuilder   .ServerSentEvents("https://localhost:7044/HttpRemote/Events"   // 接收到数据时的操作   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   })   // 连接打开时操作   .SetOnOpen(() =>   {       Console.WriteLine("连接成功。");   })   // 连接未打开时操作   .SetOnError((ex) =>   {       Console.WriteLine("连接错误。" + ex.Message);   }), cancellationToken: cancellationToken);

Server-Sent Events 特别适合那些需要服务器向客户端发送更新,但客户端不需要频繁向服务器发送请求的应用场景。无论是用于实时更新数据、提供进度报告还是实现简单的通知系统,SSE 都是一个值得考虑的选择。