当前位置: 首页 > article >正文

C#通过API接口返回流式响应内容---SignalR方式

1、背景

在上两篇《C#通过API接口返回流式响应内容—分块编码方式》和《C#通过API接口返回流式响应内容—SSE方式》实现了流式响应的内容。
上面的这两个主要是通过HTTP的一些功能,除了这些之外,还有WebSocket的方式。C#中的WebSocket的有比较多的方案:SignalRFleckFreeIMWebSocket-SharpNetCoreServer等。其中SignalR是微软官网推荐的、FleckWebSocketC#的开源项目,并且用的比较多,其他三个(FreeIM、WebSocket-Sharp、NetCoreServer)本人未使用,但原理相同,大家可以网上找找方案。
本篇主要是使用SignalR的方案

2、效果

在这里插入图片描述

3、具体代码

3.1、创建一个Hub

在这里插入图片描述
创建一个Hub服务,本质上它是一个服务器,用作一个服务转发。它是通过继承Hub实现。

using Microsoft.AspNetCore.SignalR;namespace SignalRHub.Hubs
{public class DeepSeekChat:Hub{public async Task SendDeepSeekStream(string msg){await Clients.All.SendAsync("ReceiveMsg", msg); //非常简单的方法,就是直接推送数据}}
}

3.2、配置Hub

program.cs中配置Hub

using Microsoft.AspNetCore.SignalR;using SignalRHub.Hubs;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSignalR();      //【添加SignalR服务】
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}//app.UseHttpsRedirection();
app.UseCors(MyAllowSpecificOrigins);app.UseAuthorization();app.MapControllers();
app.MapHub<DeepSeekChat>("/dschat"); //【配置Endpoint】
app.Run();

3.3、配置推送服务

当我们实现了DeepSeekChat时,我们如何通过服务器,将数据推送到终端呢?因此我们需对外的API接口,当我们调用API的接口时,API方法内部调用signalr的实例,并调用推送方法,从而将我们的内容推送到终端。
在apicontroller中或者program.cs
在apicontroller中的方法如下,【这个是一个Get方法】

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using SignalRHub.Hubs;namespace SignalRHub.Controllers
{[Route("api/[controller]")][ApiController]public class ViaAPIController : ControllerBase{private readonly IHubContext<DeepSeekChat> chatHub;public ViaAPIController(IHubContext<DeepSeekChat> chatHub){this.chatHub = chatHub;}[HttpGet("sendmsg")]public async Task SendMsg(){//模拟deepseek的对话内容var phrases = new string[] { "你好!", "我是", "北京清华长庚医院", "信息管理部的", "郑林" };foreach (var item in phrases){await chatHub.Clients.All.SendAsync("ReceiveMsg", item);await Task.Delay(1000);}}}
}

在program.cs的代码如下:

//上文中的其他配置略过
app.UseAuthorization();
app.MapControllers();
app.MapHub<DeepSeekChat>("/dschat");
//【这儿就是直接配置的,两者的效果是一样的,都是发送数据】
app.MapPost("sendNotification", async (string msg, IHubContext<DeepSeekChat> context) => {var phrases = new string[] { "你好!", "我是", "北京清华长庚医院", "信息管理部的", "郑林" };foreach (var item in phrases){await context.Clients.All.SendAsync("ReceiveMsg", item);await Task.Delay(1000);}
});app.Run();

两者的效果是一致的

3.4、前端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>SignalR Client</title><script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.18/signalr.min.js"></script>
</head>
<body><h3>流式响应</h3><div id="stockPrices"></div><script>const connection = new signalR.HubConnectionBuilder().withUrl("http://localhost:5071/dschat").build();connection.on("ReceiveMsg", (msg) => {const stockPricesDiv = document.getElementById("stockPrices");stockPricesDiv.innerHTML+= msg +'&nbsp;'; });connection.start().then(() => {console.log("SignalR connection started.");}).catch(err => {console.error("Error connecting to SignalR: ", err);});window.addEventListener("beforeunload", () => {connection.stop().then(() => {console.log("SignalR connection stopped.");}).catch(err => {console.error("Error stopping SignalR connection: ", err);});});</script>
</body>
</html>

比较简单

3.5、配置Cors

这样运行的话,浏览器是报错的,因为有Cors限制,因此需要在program.cs中配置

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";var builder = WebApplication.CreateBuilder(args);//设置CORS
builder.Services.AddCors(options => {options.AddPolicy(name: MyAllowSpecificOrigins,policy => {policy.SetIsOriginAllowed(t=>true) //默认全部访问.AllowAnyHeader().AllowAnyMethod().AllowCredentials();});
});
builder.Services.AddControllers();//其他配置//app.UseHttpsRedirection();
app.UseCors(MyAllowSpecificOrigins); //配置Cors
app.UseAuthorization();
app.MapControllers();

3.6、完整的program配置

完整的配置如下:

using Microsoft.AspNetCore.SignalR;
using SignalRHub.BackgroundServices;
using SignalRHub.Hubs;var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";var builder = WebApplication.CreateBuilder(args);//设置CORS
builder.Services.AddCors(options => {options.AddPolicy(name: MyAllowSpecificOrigins,policy => {policy.SetIsOriginAllowed(t=>true) //.AllowAnyHeader().AllowAnyMethod().AllowCredentials();});
});builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSignalR();//添加SignalR服务
//builder.Services.AddHostedService<Worker>(); //添加一个后台服务var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}//app.UseHttpsRedirection();
app.UseCors(MyAllowSpecificOrigins); //配置Corsapp.UseAuthorization();app.MapControllers();
app.MapHub<DeepSeekChat>("/dschat");app.MapPost("sendNotification", async (string msg, IHubContext<DeepSeekChat> context) => {var phrases = new string[] { "你好!", "我是", "北京清华长庚医院", "信息管理部的", "郑林" };foreach (var item in phrases){await context.Clients.All.SendAsync("ReceiveMsg", item);await Task.Delay(1000);}
});app.Run();

4、原理

在这里插入图片描述这个是一个原理图,只不过本文的样例是单向的

5、参考资料

1、SignalR微软官网
2、ASP.NET Core 配置跨域(CORS)
3、3个WebSocket的.Net开源项目

相关文章:

C#通过API接口返回流式响应内容---SignalR方式

1、背景 在上两篇《C#通过API接口返回流式响应内容—分块编码方式》和《C#通过API接口返回流式响应内容—SSE方式》实现了流式响应的内容。 上面的这两个主要是通过HTTP的一些功能&#xff0c;除了这些之外&#xff0c;还有WebSocket的方式。C#中的WebSocket的有比较多的方案&…...

vulhub靶机----基于docker的初探索,环境搭建

环境搭建 首先就是搭建docker环境&#xff0c;这里暂且写一下 #在kali apt update apt install docker.io配置docker源&#xff0c;位置在/etc/docker/daemon.json {"registry-mirrors": ["https://5tqw56kt.mirror.aliyuncs.com","https://docker…...

P1659 [国家集训队] 拉拉队排练 (manacher 算法)

P1659 [国家集训队] 拉拉队排练 - 洛谷 这题需要求前k大的回文子串的长度的乘积。因为n的大小为1e6 &#xff0c;所以我们只能使用manacher 线性的来找到所有的回文子串。 其中长度大的回文子串可以包含小的回文子串&#xff0c;所以其实我们只需要知道以每一个位置为回文中心…...

Redis命令详解--集合

Redis set 是string类型的无序集合。集合成员是唯一的&#xff0c;这就意味着集合中不能出现重复的数据&#xff0c;常用命令&#xff1a; SADD key member1 [member2...] 向集合添加一个或多个成员 SREM key member1 [member2...] 移除集合中一个或多个成员 SMEMBERS key 获…...

AI对话框实现

请注意&#xff0c;功能正在开发中&#xff0c;代码和注释不全 场景&#xff1a;AI对话框实现&#xff0c;后端调用AI大模型。前端发送请求后端返回流式数据&#xff0c;进行一问一答的对话功能&#xff08;场景和现在市面上多个AI模型差不多&#xff0c;但是没人家功能健全&a…...

可视化图解算法:删除链表中倒数第n个节点

1. 题目 描述 给定一个链表&#xff0c;删除链表的倒数第 n 个节点并返回链表的头指针 例如&#xff0c; 给出的链表为: 1→2→3→4→5, n 2. 删除了链表的倒数第 n 个节点之后,链表变为1→2→3→5. 数据范围&#xff1a; 链表长度 0≤n≤1000&#xff0c;链表中任意节点的…...

智能汽车图像及视频处理方案,支持视频智能拍摄能力

美摄科技&#xff0c;作为智能汽车图像及视频处理领域的先行者&#xff0c;凭借其卓越的技术实力和前瞻性的设计理念&#xff0c;为全球智能汽车制造商带来了一场视觉盛宴的革新。我们自豪地推出——美摄科技智能汽车图像及视频处理方案&#xff0c;一个集高效性、智能化、画质…...

如何根据 CUDA 配置安装 PyTorch 和 torchvision(大模型 环境经验)

目录 前言1. CUDA2. 环境配置前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 写过ubuntu的配置安装:Ubuntu安装配置Cuda和Pytorch gpu 以下针对Window,如何通过Cuda配置对应版本,安装大模型环境! 代码有配置包,直接执行:pip install -r requi…...

微信小程序的业务域名配置(通过ingress网关的注解)

一、背景 微信小程序的业务域名配置&#xff08;通过kong网关的pre-function配置&#xff09;是依靠kong实现&#xff0c;本文将通过ingress网关实现。 而我们的服务是部署于阿里云K8S容器&#xff0c;当然内核与ingress无异。 找到k8s–>网络–>路由 二、ingress注解 …...

自学Python创建强大AI:从入门到实现DeepSeek级别的AI

人工智能&#xff08;AI&#xff09;是当今科技领域最热门的方向之一&#xff0c;而Python是AI开发的首选语言。无论是机器学习、深度学习还是自然语言处理&#xff0c;Python都提供了丰富的库和工具。如果你梦想创建一个像DeepSeek这样强大的AI系统&#xff0c;本文将为你提供…...

Matlab 舰载机自动着舰控制系统研究

1、内容简介 Matlab 188-舰载机自动着舰控制系统研究 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

【华为OD-E卷 -123 判断一组不等式是否满足约束并输出最大差 100分(python、java、c++、js、c)】

【华为OD-E卷 - 判断一组不等式是否满足约束并输出最大差 100分(python、java、c++、js、c)】 题目 给定一组不等式,判断是否成立并输出不等式的最大差(输出浮点数的整数部分) 要求: 不等式系数为 double类型,是一个二维数组 不等式的变量为 int类型,是一维数组; 不等式…...

剑指 Offer II 113. 课程顺序

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20113.%20%E8%AF%BE%E7%A8%8B%E9%A1%BA%E5%BA%8F/README.md 剑指 Offer II 113. 课程顺序 题目描述 现在总共有 numCourses 门课需要选&#xff0c;记为 0 到 n…...

小科普《DNS服务器》

DNS服务器详解 1. 定义与核心作用 DNS&#xff08;域名系统&#xff09;服务器是互联网的核心基础设施&#xff0c;负责将人类可读的域名&#xff08;如www.example.com&#xff09;转换为机器可识别的IP地址&#xff08;如192.0.2.1&#xff09;&#xff0c;从而实现设备间的…...

嵌入式硬件篇---WIFI模块

文章目录 前言一、核心工作原理1. 物理层&#xff08;PHY&#xff09;工作频段2.4GHz5GHz 调制技术直接序列扩频正交频分复用高效数据编码 2. 协议栈架构MAC层Beacon帧4次握手 3. 核心工作模式 二、典型应用场景1. 智能家居系统远程控制环境监测视频监测 2. 工业物联网设备远程…...

WindowsAD域服务权限提升漏洞

WindowsAD 域服务权限提升漏洞&#xff08;CVE-2021-42287, CVE-2021-42278&#xff09; 1.漏洞描述 Windows域服务权限提升漏洞&#xff08;CVE-2021-42287, CVE-2021-42278&#xff09;是由于Active Directory 域服务没有进行适当的安全限制&#xff0c;导致可绕过安…...

Oracle常见系统函数

一、字符类函数 1&#xff0c;ASCII(c)和CHR(i)字符串和ascii码互转换 SQL> select ascii(Z) ,ascii(H),ascii( A) from dual;ASCII(Z) ASCII(H) ASCII(A) ---------- ---------- ----------90 72 32SQL> select chr(90),chr(72),chr(65) from dual;C…...

甘特图dhtmlx-gantt 一行多任务

继上篇进行修改 dhtmlxGantt 甘特图 一行展示多条任务类型_dhtmlxgantt多个任务显示在一行-CSDN博客 主要修改 getProductData 数据部分&#xff1a; 数据中添加&#xff1a; render: "split", //允许任务在同一行中拆分显示&#xff0c; parent: "1",…...

docker配置国内镜像站链接

修改这个文件 sudo vi /etc/docker/daemon.json将镜像站的链接放在里面&#xff0c;如果大于等于两个用逗号分隔 { "registry-mirrors": ["https://docker.1panel.live"] }使配置生效 sudo systemctl daemon-reload sudo systemctl restart docker条件允…...

Flutter 学习之旅 之 flutter 使用 SQLite(sqflite) 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装

Flutter 学习之旅 之 flutter 使用 SQLite&#xff08;sqflite&#xff09; 实现简单的数据本地化 保存/获取/移除/判断是否存在 的简单封装 目录 Flutter 学习之旅 之 flutter 使用 SQLite&#xff08;sqflite&#xff09; 实现简单的数据本地化 保存/获取/移除/判断是否存在…...

【leetcode hot 100 208】实现Trie(前缀树)

解法一&#xff1a;字典树 Trie&#xff0c;又称前缀树或字典树&#xff0c;是一棵有根树&#xff0c;其每个节点包含以下字段&#xff1a; 指向子节点的指针数组 children。对于本题而言&#xff0c;数组长度为 26&#xff0c;即小写英文字母的数量。此时 children[0] 对应小…...

Pytest的夹具共享(2)

1、问题&#xff1a;夹具跟用例都是写在一个py文件中&#xff0c;在自动化框架中&#xff0c;测试用例、夹具在不同的文件中&#xff0c;跨文件夹具使用呢&#xff1f; “”" 在XXX测试用例模块中&#xff0c;使用夹具&#xff1f; 如何跨文件调用&#xff1f; -1&#x…...

前端安全之DOMPurify基础使用

DOMPurify时一款专门用于防御XSS攻击的库&#xff0c;通过净化HTML的内容&#xff0c;移除恶意脚本&#xff0c;同时保留安全的HTML标签和数学。以下是基础使用指南&#xff0c;涵盖基础的安装与用法。 1&#xff0c;安装DOMPurify 通过npm或yarn安装 npm install dompurify …...

鸿蒙 元服务摘要

元服务&#xff08;原名原子化服务&#xff09;&#xff0c;是HarmonyOS提供的一种面向未来的服务提供方式&#xff0c;是有独立入口的&#xff08;用户可通过点击方式直接触发&#xff09;、免安装的&#xff08;无需显式安装&#xff0c;由系统程序框架后台安装后即可使用&am…...

【css酷炫效果】纯CSS实现粒子旋转动画

【css酷炫效果】纯CSS实现粒子旋转动画 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u011561335/90492008 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&…...

k8s中的service解析

k8s中的service解析 在k8s中&#xff0c;我们可以通过pod来创建服务。 然而&#xff0c;当我们创建多个 Pod 来提供同一项服务时&#xff0c;直接通过 Pod IP 进行访问会变得复杂且不可维护。因此&#xff0c;Kubernetes 提供了 Service 这一抽象概念&#xff0c;用于对外暴露…...

案例:图书管理

掌握图书管理案例的实现&#xff0c;能够使用Spring Boot整合Thymeleaf完成图书管理案例。 1.任务需求 &#xff08;1&#xff09;项目使用Spring Boot整合Thymeleaf&#xff0c;项目展示的页面效果全部通过Thymeleaf的模板文件实现。 &#xff08;2&#xff09;查询所有图书。…...

Docker和Dify学习笔记

文章目录 1 docker学习1.1 基本命令使用1.1.1 docker ps查看当前正在运行的镜像1.1.2 docker stop停止容器1.1.3 docker compose容器编排1.1.4 docker网络[1] 进入到容器里面敲命令[2] docker network ls[3] brige网络模式下容器访问宿主机的方式 2 Dify的安装和基础使用2.1 下…...

【Java集合夜话】第1篇:拨开迷雾,探寻集合框架的精妙设计

欢迎来到Java集合框架系列的第一篇文章&#xff01;&#x1f339; 本系列文章将以通俗易懂的语言&#xff0c;结合实际开发经验&#xff0c;带您深入理解Java集合框架的设计智慧。&#x1f339; 若文章中有任何不准确或需要改进的地方&#xff0c;欢迎大家指出&#xff0c;让我…...

VSCode创建VUE项目(四)增加用户Session管理

将用户信息存储或者更新到Session sessionStorage.setItem("userID",loginform.value.username); sessionStorage.setItem(loginTime, Date.now()); 获取Session信息 const storedUserInfo sessionStorage.getItem(userID); const loginTime sessionStorage.get…...