什么是SignalR?

SignalR做了什么?
传统HTTP采用的是大家熟知的“拉模式”,即客户端发出的每次请求,服务端都是被动处理。此场景下客户端是老大,很显然只有一方主动,操作与处理起来就没那么完美。

封装与集成

SignalR用途
官方网址和源码
-
官方网址:https://dotnet.microsoft.com/zh-cn/apps/aspnet/signalr
-
微软API文档:https://learn.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/introduction-to-signalr
-
GitHub网址:https://github.com/SignalR

示例截图

服务端项目创建
using Microsoft.AspNetCore.SignalR;namespace DemoSignalR.Server.Chat{public class ChatHub : Hub{#region 连接和断开连接public override async Task OnConnectedAsync(){var connId = Context.ConnectionId;Console.WriteLine($"{connId} 已连接");await base.OnConnectedAsync();}public void StartNotify(string type){if (type == "1"){}else if (type == "2"){};}public override async Task OnDisconnectedAsync(Exception ex){//如果断开连接var connId = Context.ConnectionId;Console.WriteLine($"{connId} 已断开");await base.OnDisconnectedAsync(ex);}#endregion}}
SignalR服务端业务集成
using DemoSignalR.Server.Chat;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.SignalR;namespace DemoSignalR.Server.Controllers{[ApiController][Route("[controller]")]public class TestWebApiController : ControllerBase{private readonly ILogger<TestWebApiController> _logger;private IHubContext<ChatHub> _context;public TestWebApiController(ILogger<TestWebApiController> logger, IHubContext<ChatHub> context){_logger = logger;_context = context;}[HttpGet]public void GetTestA(string Name){string info = $"当前接收到的信息为:{Name},{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}";_context.Clients.All.SendAsync("", info);}}}
using Microsoft.AspNetCore.SignalR;using System.Timers;namespace DemoSignalR.Server.Chat{public class TestChatInfo{private IHubContext<ChatHub> _context;private System.Timers.Timer _timer;private readonly static object locker = new object();//锁对象public static TestChatInfo instance;//当前实例private readonly ILogger _logger;private int _index = 0;private TestChatInfo(IHubContext<ChatHub> _context, ILogger _logger){this._context = _context;this._logger = _logger;//定义定时器_timer = new System.Timers.Timer(100);_timer.AutoReset = true;_timer.Enabled = true;_timer.Elapsed += Timer_Elapsed;_timer.Start();}private void Timer_Elapsed(object? sender, ElapsedEventArgs e){//业务逻辑判断var obj = new TestValue();obj.Index = this._index;obj.Value = DateTime.Now.Millisecond % 100;_context.Clients.All.SendAsync("RefreshInfos", obj);this._index++;}/// <summary>/// 注册,即初始化单例实例/// </summary>/// <param name="context"></param>/// <param name="reviewTaskService"></param>/// <param name="sysParamService"></param>public static void Register(IHubContext<ChatHub> context, ILogger logger){lock (locker){if (instance == null){lock (locker){instance = new TestChatInfo(context, logger);}}}}}public class TestValue{private int index;public int Index { get { return index; } set { index = value; } }private float value;public float Value { get { return value; } set { this.value = value; } }}}
SignalR服务端配置
using DemoSignalR.Server.Chat;using Microsoft.AspNetCore.SignalR;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();//1.添加SignalR服务builder.Services.AddSignalR();builder.Services.AddLogging(logging => logging.AddConsole());var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}app.UseRouting();app.UseHttpsRedirection();app.UseAuthorization();//在Use中注册单例实例app.Use(async (context, next) =>{var hubContext = context.RequestServices.GetRequiredService<IHubContext<ChatHub>>();//var logger = context.RequestServices.GetRequiredService<ILogger>();TestChatInfo.Register(hubContext, null);//调用静态方法注册if (next != null){await next.Invoke();}});app.MapControllers();//2.映射路由app.UseEndpoints(endpoints => {endpoints.MapHub<ChatHub>("/chat");});app.Run();
客户端项目创建
using Microsoft.AspNetCore.SignalR.Client;using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoSignalR.Client{internal class SignalRClient{private readonly HubConnection hubConnection;public HubConnection HubConnection{get { return hubConnection; }}public SignalRClient(){var server = ConfigurationManager.AppSettings["Server"].ToString();hubConnection = new HubConnectionBuilder().WithUrl($"{server}/chat").WithAutomaticReconnect().Build();hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(5);}public virtual void Listen(){}public async void Start(){try{await hubConnection.StartAsync();}catch (Exception e){}}}}
客户端业务逻辑处理
using Microsoft.AspNetCore.SignalR.Client;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace DemoSignalR.Client{internal class TestSignalRClient : SignalRClient{public Action<object> RefreshInfos;public Action<string> Reconnected;public TestSignalRClient() : base(){}public override void Listen(){HubConnection.On<object>("RefreshInfos", (obj) =>{//if (obj != null){Console.WriteLine("收到数据");//发送消息if (RefreshInfos != null){RefreshInfos(obj);}}});HubConnection.Reconnected += HubConnection_Reconnected;}private Task HubConnection_Reconnected(string arg){return Task.Run(() =>{if (Reconnected != null){Reconnected(arg);}});}public virtual void StartNotify(string condition){HubConnection.SendAsync("StartNotify", condition);Console.WriteLine($"开始通过知{condition}");}}}
SignalR需要注意事项
关于源码
