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. python C# DES 加密转换

    import time import base64 import pyDes import binascii def DESEncrypt(desKey, target): key = desKey[ ...

  2. 会长哥哥帮助安装ubuntu

    今晚突然想到要安装虚拟机,因为我原来上的python预科班里面讲解安装虚拟机,但是我当时没有安装上,导致预科班后面的课我没听懂,今天听课讲到字符和编码 所以想到了我的虚拟机,于是今晚很谨慎的求助会长大 ...

  3. C/C++ 数据结构单链表的实现(初始化、插入、删除、销毁)

    #include <iostream> #include <Windows.h> #define MAX_SIZE 100 using namespace std; //单链表 ...

  4. sql自学记录

    复习 SQL join :用于根据两个或多个表中的列之间的关系,从这些表中查询数据 eg: SELECT Persons.LastName, Persons.FirstName, Orders.Ord ...

  5. STM32使用DMA接收不定长数据

    开启串口,是能串口全局中断 配置DMA并勾选Memory选项 继续配置工程并且生成代码 添加一些串口通讯使用的全局变量 #define BUFFER_SIZE 128 uint8_t Tx_Buf[5 ...

  6. Windows11右键改Win10

    Win11改Win10右键模式 1.以管理员身份运行CMD控制台 2.在控制台中输入下列代码后回车执行 reg add "HKCU\Software\Classes\CLSID\{86ca1 ...

  7. .bat 脚本替换文件内容

    rem 定义变量延迟环境,关闭回显 @echo off&setlocal enabledelayedexpansion rem 读取a.txt所有内容 for /f "eol=* t ...

  8. (2)请用requests库的get()函数访问如下一个网站20次,打印返回状态,text()内容,计算text()属性和content属性所返回网页内容的长度。

    # 导入库 import requests from bs4 import BeautifulSoup def getUrlText(url): try: web = requests.get(url ...

  9. 干货来袭!3天0基础Python实战项目快速学会人工智能必学数学基础全套(含源码)(第3天)概率分析篇:条件概率、全概率与贝叶斯公式

    第1天:线性代数篇:矩阵.向量.实战编程 第2天:微积分篇:极限与导数.梯度下降.积分.实战编程 第3天:概率分析篇:条件概率与全概率.贝叶斯公式.实战项目 目录 前言 一.概率与机器学习 1.1 概 ...

  10. Harmonic Number 调和级数(欧拉常数)或者分块暴力

    给你个n让你求 Memory limit 32768 kB 输出误差不超过1e-8 思路:做之前不知都调和级数不知道欧拉常数没问题,肯定能先想到暴力打标,打完发现数组内存太大,那么问题就是怎么能让内存 ...