业务情景一:上传报表,上传excel。如果excel的数据量很大,上万条,上十万条数据,那么这个上传请求必然是个耗时请求。用户上传之后,很关心上传的进度和结果。
业务情景二:站内消息提醒,实时有效地接受消息。
对于这些需求,第一时间想到的是,前端定时去轮询数据,返回一个进度或者未读的站内消息。
这样虽然能达到目的,但是付出的代价是昂贵的。站点24小时,不断地在请求接口,数据库不断地在被访问,这是客户端主动请求所带来的弊端。
换一个角度,如果是服务端主动去推送消息给客户端,那么性能势必能大幅增加,同时推送的消息更为及时、准确。
SignalR对常用实时通讯技术进行了封装, SignalR当WebSocket可用时优先使用新式的WebSocket传输,同时也兼容老式的传输。
SignalR支持以一种简单的API来创建服务器到客户端的远程调用客户端的Javascript方法,SignalR还包括用于用于连接管理的API和分组连接。
新建一个.net core console程序,引入nuget包
以下是服务端代码,主程序创建了一个站内,站点启动时注入了一个hubcontext的实例,这个hubcontext的主要工作是,每隔一秒钟触发客户端去执行OnReportPublished方法。
1 using Microsoft.AspNetCore; 2 using Microsoft.AspNetCore.Builder; 3 using Microsoft.AspNetCore.Hosting; 4 using Microsoft.AspNetCore.SignalR; 5 using Microsoft.Extensions.DependencyInjection; 6 using System; 7 using System.Threading; 8 using System.Threading.Tasks; 9 10 namespace OneCode.SignalR 11 { 12 public class Program 13 { 14 public static void Main(string[] args) 15 { 16 BuildWebHost(args).Run(); 17 } 18 19 public static IWebHost BuildWebHost(string[] args) => 20 WebHost.CreateDefaultBuilder(args) 21 .UseStartup<Startup>() 22 .Build(); 23 } 24 25 public class MyHub : Hub 26 { 27 //此方法用于被客户端调用,当客户端执行 hubConnection.invoke('PublishReport', $('#reportName').val()); 会触发此方法执行 28 public Task PublishReport(string reportName) 29 { 30 //主动通知客户端去执行客户端本身的方法,此代码执行后 31 //hubConnection.on('OnReportPublished', data => { 32 // $('#reports').append($('<li>').text(data)); 33 //}); 34 35 //客户端将执行 OnReportPublished 36 return Clients.All.InvokeAsync("OnReportPublished", reportName); 37 } 38 39 public async void Echo(string sendMan) 40 { 41 while (true) 42 { 43 await Clients.All.InvokeAsync("OnReportPublished", $"{DateTime.Now}:{sendMan}:{ Guid.NewGuid().ToString()}"); 44 Thread.Sleep(1 * 1000); 45 } 46 } 47 } 48 49 public class Startup 50 { 51 public void ConfigureServices(IServiceCollection services) 52 { 53 services.AddCors(options => 54 { 55 options.AddPolicy("fiver", 56 policy => policy.AllowAnyOrigin() 57 .AllowAnyHeader() 58 .AllowAnyMethod()); 59 }); 60 61 services.AddSignalR(); // <-- SignalR 62 63 } 64 65 public void Configure(IApplicationBuilder app, IHostingEnvironment env) 66 { 67 app.UseDeveloperExceptionPage(); 68 app.UseCors("fiver"); 69 70 app.UseSignalR(routes => // <-- SignalR 71 { 72 routes.MapHub<MyHub>("myHub"); 73 }); 74 75 //IHubContext<MyHub> hubContext = serviceProvider.GetService<IHubContext<MyHub>>(); 76 } 77 } 78 }
以下是客户端代码
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>ASP.NET Core SignalR</title> <script src="js/signalr-client.min.js"></script> <script src="js/jquery.min.js"></script> </head> <body> <div> <h2>Reports</h2> <button id="button">send</button> <ul id="reports"></ul> <script> $(function () { let hubUrl = 'http://localhost:5000/myHub'; let httpConnection = new signalR.HttpConnection(hubUrl); let hubConnection = new signalR.HubConnection(httpConnection); $("#button").click(function () { hubConnection.invoke('Echo', 'wiky'); }); hubConnection.on('OnReportPublished', data => { $('#reports').append($('<li>').text(data)); }); hubConnection.start(); }); </script> </div> </body> </html>
以下是执行结果: