• .NET使用Server-Sent Events实现打字聊天效果
  • 发布于 2个月前
  • 178 热度
    0 评论
  • 亦東風
  • 0 粉丝 41 篇博客
  •   
你是否注意过,当我们向ChatGPT提问后,它并不是立刻返回全部答案,而是一段段的输出,并伴有一定时间的延迟,好像在思考一样。

一直很好奇这种效果如何实现的,直到最近了解到了Server-Sent Events。

Server-Sent Events
Server-Sent Events(SSE)是一种基于HTTP协议的服务器推送技术,它的原理是这样的:
1.客户端向服务器发送一个HTTP请求,请求一个特定的资源,比如一个API接口。
2.服务器接收到请求后,不会立刻返回响应,而是保持连接打开,并且定期向客户端发送一些文本消息。
3客户端监听这些消息,并根据类型和内容来执行相应的操作。

这样,服务器就可以在任何时候向客户端发送数据,而不需要等待客户端的请求。因此,SSE可以用来实现实时更新、通知、进度条等功能。

例子
要使用Server-Sent Events,我们需要分别在前端和后端做一些设置。在后端,我们需要设置响应头Content-Type: text/event-stream,这样就可以告诉浏览器,我们返回的是一个SSE响应流。然后,我们就可以按照一定的格式向客户端发送数据了。每个数据都是一个文本消息,消息的格式如下:
event: <event-name>  // 可选,消息类型
id: <message-id>     // 可选,消息ID
data: <message>      // 必须,消息内容
retry: <timeout>     // 可选,连接中断后重连的时间间隔
我们使用.NET Minimal API来实现一个简单的服务器,代码如下:
app.MapGet("/sse", async (HttpContext context, CancellationToken cancellationToken) =>
{
    context.Response.Headers.Add("Content-Type", "text/event-stream");
    // 堆代码 duidaima.com
    await foreach (var item in GetAnswerAsync())
    {
        await context.Response.WriteAsync("event: message\n");
        await context.Response.WriteAsync($"data: {item}\n\n");        
        await context.Response.Body.FlushAsync();
    }

    await context.Response.WriteAsync("event: close\n");
    await context.Response.WriteAsync($"data: \n\n");
    await context.Response.Body.FlushAsync();
});
在上面的代码中,我们发送了两种事件类型的消息,一种是message,一种是close,前者是表示返回的数据,后者是表示断开连接。在前端,我们需要创建一个EventSource对象,并传入API的URL作为参数。然后,我们就可以监听各种事件了。每个事件都有一个event属性和一个data属性,分别表示事件类型和事件内容。
<html>
<body>
    <script>
        function display() {
            var source = new EventSource('/sse');
            var div = document.getElementById("sse");
            source.addEventListener("message", (e) => {
                div.innerText += e.data
            });
            source.addEventListener("close", (e) => {
                source.close()
            });
        }
        window.addEventListener("DOMContentLoaded", display, false);
    </script>
    <div id="sse" style="width:300px;height:300px;background-color:lightgrey"/>
</body>
</html>
我们可以看到,前端页面会不断的显示服务器返回的消息,直到服务器返回close事件。

总结
本文介绍了Server-Sent Events(SSE)这种基于HTTP协议的服务器推送技术,它可以让服务器在任何时候向客户端发送数据,而不需要等待客户端的请求。它的优点是使用标准的HTTP协议,浏览器支持非常好,不需要额外的服务器或客户端库支持,比WebSocket更简单和轻量。

它的缺点是只能使用文本消息,并且只能单向发送数据,不能实现双向通信,如果需要实现双向通信,需要使用WebSocket。
用户评论