SignalR使用案例
由客户端使用SignalR向服务端发起而建立的连接是平等的通讯
本次案例服务端为ASP.NET Core Web API,客户端为ConsoleApp
一、创建项目
分别创建ASP.NET Core Web API和ConsoleApp项目
二、配置SignalR服务端
- 创建自定义Hub,配置由客户端调用的方法
- 方法ReciveMsgByClient由客户端调用
public class SignalRHub:Hub { public SignalRHub() { } public void ReciveMsgByClient(string msg) { Debug.WriteLine(msg); } public override Task OnConnectedAsync() { return base.OnConnectedAsync(); } public override Task OnDisconnectedAsync(Exception? exception) { return base.OnDisconnectedAsync(exception); } }
- 配置Program文件
- 添加builder.Services.AddSignalR();
- 注入SignalRHub并指定"/signalr"为连接路径
using Microsoft.AspNetCore.SignalR; using SignalRWebApplication.WebHub; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //添加SignalR服务 builder.Services.AddSignalR(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.MapHub<SignalRHub>("/signalr"); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
- 配置Controller调用
[ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private readonly IHubContext<SignalRHub> _hubContext; public WeatherForecastController(IHubContext<SignalRHub> hubContext) { _hubContext = hubContext; } [HttpGet] [Route("/sendmsg")] public void SendMsg() { _hubContext.Clients.All.SendAsync("ReciveMsg","Hey!:from Server"); } }
三、配置客户端
引用此包:Microsoft.AspNetCore.SignalR.Client
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Diagnostics;
namespace SignalRConsoleApp
{
internal class Program
{
[STAThread]
static void Main(string[] args)
{
HubConnection hubConnection=new HubConnectionBuilder()
.WithUrl("https://localhost:7132/signalr")
//自动重连频率,也可以通过实现IRetryPolicy进行配置
.WithAutomaticReconnect(new[] { TimeSpan.Zero,
TimeSpan.Zero,
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10),
TimeSpan.FromSeconds(20),
TimeSpan.FromSeconds(10),
TimeSpan.FromMinutes(1),
TimeSpan.FromMinutes(3),
TimeSpan.FromMinutes(5) })
.Build();
hubConnection.Reconnected += connectionId =>
{
Debug.Assert(hubConnection.State == HubConnectionState.Connected);
Console.WriteLine("WS重新链接成功");
return Task.CompletedTask;
};
hubConnection.On<string>("ReciveMsg", (msg) =>
{
Debug.WriteLine(msg);
hubConnection.SendAsync("ReciveMsgByClient","Hi!:from client");
});
Task task = Task.Run(async () => { await hubConnection.StartAsync(); });
task.Wait();
if (task.IsCompleted)
{
Debug.WriteLine("已建立连接");
}
Console.ReadLine();
}
}
}
注:
代码中hubConnection.On(“ReciveMsg”, (msg) =>{}),"ReciveMsg"为服务端调用的标识字符串
hubConnection.SendAsync(“ReciveMsgByClient”,“Hi!:from client”);中"ReciveMsgByClient"为客户端调用服务端方法的标识字符串
四、扩展
1.配置Token
- 客户端配置Token(JWT)
HubConnection hubConnection = new HubConnectionBuilder() .WithUrl(url, options => { //配置连接Token值 options.AccessTokenProvider = () => Task.FromResult(Token); }) //自动重连频率,也可以通过实现IRetryPolicy进行配置 .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(10), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(5) }) .Build();
- 服务端配置Token鉴权
仅允许Role为Admin的Token客户端连接[Authorize(Roles ="Admin")] public class SignalRHub:Hub { public SignalRHub() { } public void ReciveMsgByClient(string msg) { Debug.WriteLine(msg); } public override Task OnConnectedAsync() { return base.OnConnectedAsync(); } public override Task OnDisconnectedAsync(Exception? exception) { return base.OnDisconnectedAsync(exception); } }
X.提示
更加详细的使用请参考微软官方文档
1.服务端可对连接进行分组调用
2.服务端可获取连接id,然后通过连接id调用指定客户端
3.服务端可感知到任何情况下客户端的连接断开