Websocket、SSE(Server-Sent Events)和长轮询(Long Polling)都是用于网页和服务端通信的技术。

Websocket是一种全双工通信协议,能够实现客户端和服务端之间的实时通信。它基于TCP协议,并且允许服务器主动向客户端推送数据,同时也允许客户端向服务器发送数据。

SSE是一种单向通信协议,允许服务器向客户端推送数据,但不支持客户端向服务器发送数据。SSE建立在HTTP协议上,通过在HTTP响应中使用特殊的Content-Type和事件流(event stream)格式来实现。

长轮询是一种技术,客户端向服务器发送一个请求,并且服务器保持连接打开直到有数据可以返回给客户端。如果在指定的时间内没有数据可用,则服务器会关闭连接,客户端需要重新建立连接并再次发起请求。

New Bing聊天页面是通过WebSocket进行通信。

Open AI的ChatGPT接口则是通过SSE协议由服务端推送数据

事实上,以上几种方式包括长轮询,都可以实现逐字显示的效果。那还有没有其他的办法可以实现这种效果了呢?

流式响应

当客户端返回流的时候,客户端可以实时捕获到返回的信息,并不需要等全部Response结束了再处理。

下面就用ASP.NET Core Web API作为服务端实现流式响应。

返回文本内容

服务端

[HttpPost("text")]
public async Task Post()
{
string filePath = "文档.txt";
Response.ContentType = "application/octet-stream";
var reader = new StreamReader(filePath);
var buffer = new Memory<char>(new char[5]);
int writeLength = 0;
//每次读取5个字符写入到流中
while ((writeLength = await reader.ReadBlockAsync(buffer)) > 0)
{
if (writeLength < buffer.Length)
{
buffer = buffer[..writeLength];
}
await Response.WriteAsync(buffer.ToString());
await Task.Delay(100);
}
}

客户端

  1. C# HttpClient
public async void GetText()
{
var url = "http://localhost:5000/config/text";
var client = new HttpClient();
using HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url);
var response = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead);
await using var stream = await response.Content.ReadAsStreamAsync();
var bytes = new byte[20];
int writeLength = 0;
while ((writeLength = stream.Read(bytes, 0, bytes.Length)) > 0)
{
Console.Write(Encoding.UTF8.GetString(bytes, 0, writeLength));
}
Console.WriteLine();
Console.WriteLine("END");
}

HttpCompletionOption枚举有两个值,默认情况下使用的是ResponseContentRead

  • ResponseContentRead:等到整个响应完成才完成操作

  • ResponseHeadersRead:一旦获取到响应头即完成操作,不用等到整个内容响应

  1. js XMLHttpRequest
<script>
var div = document.getElementById("content")
var url = "http://localhost:5000/config/text"
var client = new XMLHttpRequest()
client.open("POST", url)
client.onprogress = function (progressEvent) {
div.innerText = progressEvent.target.responseText
}
client.onloadend = function (progressEvent) {
div.append("END")
}
client.send() </script>

用axios请求就是监听onDownloadProgress 了。

浏览器是通过Response Header中的Content-Type来解析服务端响应体的。如果后端接口没有设置Response.ContentType = "application/octet-stream"onprogress只会在响应全部完成后触发。

返回图片

服务端

[HttpGet("img")]
public async Task Stream()
{
string filePath = "pixelcity.png";
new FileExtensionContentTypeProvider().TryGetContentType(filePath, out string contentType);
Response.ContentType = contentType ?? "application/octet-stream";
var fileStream = System.IO.File.OpenRead(filePath);
var bytes = new byte[1024];
int writeLength = 0;
while ((writeLength = fileStream.Read(bytes, 0, bytes.Length)) > 0)
{
await Response.Body.WriteAsync(bytes, 0, writeLength);
await Task.Delay(100);
}
}

ASP.NET Core Web API 流式返回,逐字显示的更多相关文章

  1. ASP.NET Core Web API下事件驱动型架构的实现(二):事件处理器中对象生命周期的管理

    在上文中,我介绍了事件驱动型架构的一种简单的实现,并演示了一个完整的事件派发.订阅和处理的流程.这种实现太简单了,百十行代码就展示了一个基本工作原理.然而,要将这样的解决方案运用到实际生产环境,还有很 ...

  2. ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件

    前言: 从开始学习Vue到使用element-ui-admin已经有将近快两年的时间了,在之前的开发中使用element-ui上传组件el-upload都是直接使用文件选取后立即选择上传,今天刚好做了 ...

  3. ASP.NET Core Web API 教程 - Project Configuration

    ASP.NET Core Web API 教程 本系列文章主要参考了<Ultimate ASP.NET Core 3 Web API>一书,我对原文进行了翻译,同时适当删减.修改了一部分内 ...

  4. 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务

    在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...

  5. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  6. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

  7. 在docker中运行ASP.NET Core Web API应用程序

    本文是一篇指导快速演练的文章,将介绍在docker中运行一个ASP.NET Core Web API应用程序的基本步骤,在介绍的过程中,也会对docker的使用进行一些简单的描述.对于.NET Cor ...

  8. 在Mac下创建ASP.NET Core Web API

    在Mac下创建ASP.NET Core Web API 这系列文章是参考了.NET Core文档和源码,可能有人要问,直接看官方的英文文档不就可以了吗,为什么还要写这些文章呢? 原因如下: 官方文档涉 ...

  9. ASP.NET Core Web API 开发-RESTful API实现

    ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...

  10. Docker容器环境下ASP.NET Core Web API

    Docker容器环境下ASP.NET Core Web API应用程序的调试 本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Dock ...

随机推荐

  1. 电脑日常维护技巧(windows系统)

    一.磁盘检测 cmd-->chkdsk 二.磁盘修复 cmd-->sfc/scannow 三.删除缓存文件 运行-->%temp%

  2. 7、jmeter配置元件-HTTP信息头配置元件

    根据对方服务器的要求来配置消息头 (重点)Gzip:发送给你压缩包  提高速度 性能等等 同样的数据  只要页面没有变更 就不会重新压缩 节省带宽

  3. 【原创】GmSSL Android库编译

    相关内容: GmSSL Linux编译 环境搭建 重要 用编译方法2编译出的库,集成到工程之后,发现报 incompatible target错误,各种找不到定义.32位和64位都不行. 如果你也遇到 ...

  4. .net 生成Excel并保存

    void SaveQuestionToExcel(List<Question> datas, string path) { using (Workbook workbook = new H ...

  5. 02 HTML基础-图片和音视频

    1.HTML中的图片 HTML5的<figure>和<figcaption>为图片提供了一个语义容器,在标题和图片之间建立了清晰的联系.<figcaption>元素 ...

  6. (Linux服务器)git添加SSH公钥后本地验证失败

    环境:腾讯云Ubuntu x86_64 问题说明: 在配置了公钥后,一直提示我git@github.com: Permission denied (publickey). 解决办法: 先查看root/ ...

  7. word多级标题自动编号设置

    1.选择段落 ->多级列表 ->定义新的多级列表 2.级别设置 ,这里操作比较繁琐,要多注意[输入编号的格式]要通过[包含的级别编号来自]这一项目来设定 标题1: 标题2 标题3: 标题4 ...

  8. windows下配置JDK教程

    1.思路: 首先要确定所要用的应用可以兼容哪个版本jdk,然后开始下载对应的版本,最后安装,配置环境变量,测试,部署完成. 2.jdk下载地址: 如果下载全新的jdk可以直接百度jdk官网下载 如果需 ...

  9. 【Mybatis-Plus】使用updateById()、update()将字段更新为null或者空

    参考 https://blog.csdn.net/weixin_41544866/article/details/119738605

  10. 阿里云镜像创建Spring Boot工厂

    参考博客:https://blog.csdn.net/qq_40052237/article/details/115794368 http://start.aliyun.com