SignalR
Posted 生命不息bug不止
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SignalR相关的知识,希望对你有一定的参考价值。
SignalR是一个可以让服务器向客户端实时推送消息的库
上图是他基本原理,多个客户端连接同一个服务器,当客户端A调用服务器的方法时,服务器会调用所有客户端的方法,这样客户端B和客户端C,虽然没做操作,但是依然会收到消息
例如QQ群聊天,一个人发出一条消息,其他人都会收到这条消息
首先要添加一个名为Startup的类(并不知道这个类是干嘛的,但我猜是注册)
public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } }
然后我们开始写服务端
服务端的类必须要继承Hub类
public class SigHub:Hub { }
然后在这个类中写一些方法,供客户端调用
public class SigHub:Hub { public void ServerShow(string text) { Clients.All.clientShow(text); } }
方法内的操作是调用所有客户端的clientShow方法(虽然我们客户端还没写,这个方法自然也还没有,但是不要紧,后面记得写上就行)
到这里我们就能大致明白上面说的基本原理和图了
一个客户端调用服务端的ServerShow方法,然后ServerShow调用所有客户端的clientShow方法
接下来我们去写客户端
客户端是网页,写在js中
首先引用三个必要的js文件
<script src="Scripts/jquery-1.6.4.js"></script> <script src="Scripts/jquery.signalR-2.2.2.js"></script> <script src="/signalr/hubs"></script>
第三个文件是生成的,项目里看不到,总之写上就行了
第一步 帮你的服务端类存到变量里
注 sigHub是你服务端里写方法的类名
var hub = $.connection.sigHub;
然后把服务端调用的客户端方法创建出来
hub.client.clientShow = function (date) {
alert(date);
}
最后调用服务端的方法
$.connection.hub.start().done(function () {
hub.server.serverShow("12313");
});
完整代码
<script> var hub = $.connection.sigHub; hub.client.clientShow = function (date) { alert(date); } $.connection.hub.start().done(function () { hub.server.serverShow("12313"); }); </script>
SignalR有几种不同的推送方式
Clients.Caller 推送给当前用户(大概)
Clients.All 推送给所有用户
Clients.Others 推送给自己以外所有的用户
Clients.Client(connectionid) 推送给指定的用户
Clients.Group(GroupId) 推送给指定组中的用户
Core版本的使用
引用core版本类库
Install-Package Microsoft.AspNetCore.SignalR -Version 1.0.0-alpha2-final (还没有正式版)
建立一个hub类,和framework的一样要继承于Hub
然后对Startup进行配置
在ConfigureServices中加上 services.AddSignalR();
public void ConfigureServices(IServiceCollection services) { services.AddSignalR(); //↓用来跨域的不用在意 services.AddCors(options => { options.AddPolicy("any", builder => { builder.AllowAnyOrigin() //允许任何来源的主机访问 .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials();//指定处理cookie }); }); services.AddMvc(); //← 本来就有的不用在意 }
之后在Configure中注册我们的hub类
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //↓本来就有 if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //↓加上才能访问wwwroot中的静态文件 app.UseFileServer(); //↓跨域 app.UseCors("any"); //↓注册hub app.UseSignalR(routes => { routes.MapHub<SigHub>("sigHub"); }); //↓路由设置为MVC那样 app.UseMvcWithDefaultRoute(); //↓本来就有 app.UseMvc(); }
这样我们的SignalR就配置好了,接下来就是如何使用
首先是我们的hub类,变化并不是很大,但还是有不同的地方
public void Test(string msg) { Clients.All.test(msg); //←framework的写法 Clients.All.InvokeAsync("test",msg); //←core的写法 }
我把两个的写法放到一起给你们对比一下,这样更清楚变化
framework版本是直接在后面点客户端的方法名来调用,参数也是直接放在方法的括号中就行了
core版本的点后面则是一个固定的方法InvokeAsync
方法的第一个参数是客户端的方法名,第二个参数是要传的参数
如果不止一个参数的话,直接在后面继续写就行了
Clients.All.InvokeAsync("test","参数1","参数2","参数3");
对客户端的几种不同调用方式
All 全部调用
Client 调用指定的客户端
Group 调用指定组当中的客户端
(other不知为什么没有了)
以上就是服务端的写法,接下来讲解客户端的写法
客户端的变化就比较大了
它需要引用一个名为signalr-client-1.0.0-alpha2-final的js文件
首先要创建一个连接对象
var transport = signalR.TransportType.LongPolling; //连接类型 var connection = new signalR.HubConnection(`http://localhost:65449/sigHub`, { transport: transport }); //创建连接对象 connection.start();//打开连接
之后是注册服务端调用的客户端方法
connection.on("test", function (msg) { $("ul").append("<li>" + msg + "</li>"); });
function中的msg就是从服务端传过来的参数
最后是调用服务端的方法
$("#send").click(function () { var date = "abc"; connection.invoke("test",date); //调用服务端的Test方法 });
注意:即使在服务端写的方法名是开头大写的,客户端调用时也要小写
date则是传给服务端的参数,不需要传参的话就不用写
connection.invoke("test");
页面的代码
<button id="send">发送</button> <ul> </ul>
完整的代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="jquery.js"></script> <script src="signalr-client-1.0.0-alpha2-final.js"></script> <script> $(function () { var transport = signalR.TransportType.LongPolling; //连接类型 var connection = new signalR.HubConnection(`http://localhost:65449/sigHub`, { transport: transport }); //创建连接对象 connection.start(); //打开连接 //注册客户端方法 connection.on("test", function (msg) { $("ul").append("<li>" + msg + "</li>"); }); //调用服务端方法 $("#send").click(function () { var date = "abc"; connection.invoke("test",date); }); }) </script> </head> <body> <button id="send">发送</button> <ul> </ul> </body> </html>
效果
这就是SignalR的Core版本使用了,最后说下跨域
SignalR的hub类可以被跨域访问,只要普通的配置一下core的api跨域就行了,这里就不说了 (其实在上面的配置中已经把跨域配置也写出来了)
以上是关于SignalR的主要内容,如果未能解决你的问题,请参考以下文章
SignalR OnConnected 与多台服务器和 Redis 背板
角度 SignalR 经常断开连接并显示错误状态代码 1006
websocket握手代码期间无法连接signalR错误:400