C# SignalR使用方法 C#如何实现实时通信

11次阅读

SignalR 是 .NET 实时通信库,自动在 websocket 等协议间降级;适用于服务端主动推送场景(如聊天、通知),不适用于高频交易或点对点通信。

C# SignalR使用方法 C#如何实现实时通信

SignalR 是什么,什么时候该用它

SignalR 是 .NET 平台上的实时通信库,本质是自动在 WebSocket、Server-Sent Events、长轮询之间做降级选择。它不是“必须用 WebSocket 才算实时”,而是帮你屏蔽传输细节,专注业务逻辑。如果你需要服务端主动推数据(比如聊天、通知、仪表盘刷新),又不想自己维护连接心跳、重连、分组广播这些逻辑,SignalR 就是合理选择。

注意:它不适用于高吞吐低延迟的场景(如高频交易),也不适合纯客户端点对点通信(该用 WebRTC)。

服务端配置:Startup.cs 或 Program.cs 中启用 SignalR

在 .NET 6+ 的 Program.cs 中,需注册 Hub 服务并映射路由:

builder.Services.AddSignalR(); // ... 其他服务 app.MapHub("/hub/chat");

其中 ChatHub继承Hub 的类,路径 /hub/chat 就是客户端连接的目标地址。别漏掉 AddSignalR(),否则运行时会报 InvalidOperationException: No service for type 'microsoft.AspNetCore.SignalR.IHubContext`1[...]'

常见疏忽:

  • Hub 类没加 public 访问修饰符 → 客户端调用方法时静默失败
  • 映射路径和前端连接 URL 不一致(比如写成 /chat 却在 js 里连 /hub/chat)→ 连接 404
  • iis 部署时未启用 WebSocket 支持 → 自动降级到长轮询,但延迟明显升高

客户端连接与调用:javaScript 端怎么写

用官方 @microsoft/signalr 包,不能直接 fetch 或 axios

const connection = new signalR.HubConnectionBuilder()   .withUrl("/hub/chat")   .configureLogging(signalR.LogLevel.Information)   .build(); 

await connection.start(); // 必须 await,否则后续调用可能失败

connection.on("ReceiveMessage", (user, message) => { console.log(${user}: ${message}); });

await connection.invoke("SendMessage", "Alice", "Hello");

关键点:

  • invoke 用于调用服务端方法,返回 promiseon 用于监听服务端推送的方法名,大小写必须和服务端 Client 方法签名完全一致
  • 服务端若用 await Clients.All.SendAsync("ReceiveMessage", ...) 推送,客户端必须已注册 connection.on("ReceiveMessage", ...),否则消息丢弃无提示
  • 连接中断后不会自动重连(除非显式调用 withAutomaticReconnect()

C# 客户端调用 Hub:比如 windows 服务或控制台程序

Microsoft.AspNetCore.SignalR.Client NuGet 包:

var connection = new HubConnectionBuilder()   .WithUrl("https://localhost:5001/hub/chat")   .Build(); 

connection.On("ReceiveMessage", (user, msg) => Console.WriteLine($"{user}: {msg}"));

await connection.StartAsync();

await connection.InvokeAsync("SendMessage", "Bob", "Hi from console");

注意:

  • 控制台程序需用 async Main,否则 await connection.StartAsync() 无法执行
  • 证书问题:若服务端用 HTTPS + 自签名证书,C# 客户端需配置 .AddHttpClient().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true })
  • 服务端方法参数类型要和客户端传入的严格匹配,比如传 int 却定义为 long → 调用静默失败,日志只显示“Failed to invoke”

Hub 方法的复杂对象序列化依赖 System.Text.json,默认不支持字段、私有 set、循环引用——这些地方最容易出无声故障。

text=ZqhQzanResources