SignalR学习
SignalR是一个.NET Core/.NET Framework的开源实时框架
SignalR可使用Web Socket,Server Sent Events 和 Long Polling作为底层传输方式
SignalR这个框架分服务器端和客户端,服务器端支持ASP.NET Core 和ASP.NET;而客户端除了支持浏览器里的javascript以外,也支持其他类型的客户端,例如桌面应用。
回落机制
Web Socket是最好的最有效的传输方式,如果浏览器或Web服务器不支持它的话,将会降级使用SSE,实在不行就用Long Polling
一旦建立连接,SignalR就会开始发送Keep alive 消息,来检查连接是否还正常。如果有问题,就会抛出异常。
SignalR默认采用回落机制来进行传输和连接。也可以禁用回落机制,只采用其中一种传输方式
RPC
RPC(Remote Procedure Call) 它的优点就是可以像调用本地方法一样调用远程服务
SignalR才用RPC方式来进行客户端与服务端之间的通信
SignalR利用底层传输来让服务器可以调用客户端的方法,反之亦然,这些方法可以带参数,参数可以是复杂对象,SignalR负责序列化和反序列化
Hub
Hub是SignalR的一个组件,运行在ASP.NET Core应用里,它是服务器的一个类
Hub使用RPC接收从客户端发来的消息,也能把消息发送给客户端。它就是一个通信用的Hub
SignalR在ASP.NET Core里面的应用:学习连接 https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio
创建 SignalR 中心
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
-
在 SignalRChat 项目文件夹中,创建 Hubs 文件夹 。
-
在 Hubs 文件夹中,使用以下代码创建 ChatHub.cs 文件 :
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRChat.Hubs { public class ChatHub : Hub { /// <summary> /// 客户端连接 /// </summary> /// <returns></returns> public override async Task OnConnectedAsync() { await base.OnConnectedAsync(); } /// <summary> /// 取消连接 /// </summary> /// <param name="exception"></param> /// <returns></returns> public override async Task OnDisconnectedAsync(Exception exception) { await base.OnDisconnectedAsync(exception); } /// <summary> /// 用户登陆客户端 /// </summary> /// <param name="id"></param> /// <returns></returns> public async Task UserLogin(string id) { //UserInfo userInfo = new UserInfo() //{ // ConnectionId = Context.ConnectionId, // Id = id //}; //UserDataManager.User.Add(userInfo); await Clients.Caller.SendAsync("AnyOne", id + "连接成功"); } } }
ChatHub
类继承自 SignalRHub
类。Hub
类管理连接、组和消息。可通过已连接客户端调用
SendMessage
,以向所有客户端发送消息。 本教程后面部分将显示调用该方法的 JavaScript 客户端代码。 SignalR 代码是异步模式,可提供最大的可伸缩性。
配置 SignalR
必须配置 SignalR 服务器,以将 SignalR 请求传递到 SignalR。
-
将以下突出显示的代码添加到 Startup.cs 文件 。
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddSignalR(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseSignalR(routes => { routes.MapHub<ChatHub>("/chatHub"); }); app.UseMvc(); } }
这些更改将 SignalR 添加到 ASP.NET Core 依赖关系注入系统和中间件管道。
Controller消息发送
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using SignalRTestCore.SignalR; namespace SignalRTestCore.Controllers { [Route("[controller]")] [ApiController] public class PushController : ControllerBase { private IHubContext<ChatHub> _hubContext; public PushController(IHubContext<ChatHub> hubContext) { _hubContext = hubContext; } [HttpPost] public async Task AnyOne(string message) { await _hubContext.Clients.All.SendAsync("AnyOne", message); } } }
客户端代码(项目使用的是Vue框架) 学习连接 https://www.npmjs.com/package/@aspnet/signalr
安装signalR插件 npm install @aspnet/signalr
const signalR = require('@aspnet/signalr') let path = "https://www.xxx.com/api"; let token ="Bearer ...."; let id="f30675f6-f488-4e41-8f47-6b50a1beccca"; const connection = new signalR.HubConnectionBuilder() .withUrl(path + '/signalr/chathub', { accessTokenFactory: () => String(token).replace("Bearer ", "") }) .build() //连接 connection.start().then(() => { connection.invoke('UserLogin', id).then(() => { }); }); //接收消息 connection.on('AnyOne', data => { console.log("AnyOne", data); })