在持久性连接的基础上,SignalR提供了一个更高层次的抽象层:Hub,基于javascript的灵活性和C#的动态特性,Hub是一个至关重要的开发模式,它消弭了客户端和服务端这两个独立的物理环境之间的界限。
在Web环境中最通用的使用模式允许我们透明地在客户端和服务端之间进行方法调用。这就是双向RPC,即可以直接从客户端调用服务器端的方法,同时服务端也可以调用客户端的方法。
为了实现以上的功能,SignalR将借助服务器Hub类在客户端自动创建代理对象,并在它们的方法中输入它们实际方法的远程调用;相反,当服务器端调用客户端某个方法时它将被一个服务器端打包这些调用的动态类型的特殊协议所解析并使用底层传输协议同构推送到其他断点,然后它们将达到各个客户端,并在客户端进行解释和运行。
现在,在服务端建立Hub类,如:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.AspNet.SignalR; namespace WebApplication2 { public class TestHub : Hub { public void Hello() { Clients.All.hello(); } } }
与持久性连接不同,基于Hub的服务不需要在启动时映射指定的Hub和和访问的URL,因为系统默会自动查找相关的Hub类,同时它们可以通过一个单独的基URL(/SignalR)进行访问,当然,为了方便这个基URL可以更改:
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; using Microsoft.AspNet.SignalR; [assembly: OwinStartup(typeof(WebApplication2.Startup))] namespace WebApplication2 { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR();//默认映射路径"/SignalR" //或 app.MapSignalR("/test",new HubConfiguration());//自己设定访问路径,同时设置Hub配置项,无需指定启动的Hub类,因为它们被自动识别 } } }
在TestHub类中,
public class TestHub : Hub { public void Hello() { Clients.All.sayHi("你好"); } }
Hello是TestHub类中的一个方法,这个方法可以给客户端用js调用。
在这个方法里面,Clients.All.sayHi()表示向所有的客户端发起调用客户端用js写的sayHi函数。
为了防止暴露TestHub真实的名称,我们可以为它起个别名Test.因为这个别名会在客户端调用的时候用到。
[HubName("test")] public class TestHub : Hub { //省略部分代码 }
除了服务端可以向所有客户端通知调用客户端方法之外,还可以对其中想要发送的客户端进行限制。同时Clients这个属性有很多动态成员供我们使用:
Clients.All:允许“调用”连接到此Hub上的所有客户端的一个方法
Clients.AllExcept:表示该调用必须发送给所有客户端,但是除了那些作为参数的connectionId以外。这里的参数可以是connectionId字符串、数组等
Clients.Caller 确定调用者的接收者是目前调用正在执行Hub方法的客户端
Clients.Client:将对方法的调用发送给指定connectionId的客户端,参数可以是字符串,也可以是数组
Client.Others :代表所有已连接的客户端,但是不包括正在调用该方法的客户端。
在方法中可以通过访问 this.Context.ConnectionId来获得当前掉用方法的客户端唯一标识符
在服务端TestHub类中已经定义好了一个hello的方法,同时该方法的目的就是在所有客户端中调用sayHi方法。
现在开始建立客户端:
新建一个html页面,在代码中写下如下代码:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="Scripts/jquery-1.10.2.min.js"></script> <script src="Scripts/jquery.signalR-2.1.2.min.js"></script> <script > $(function () { //不是用代理进行与服务器通信 var connection = $.hubConnection("/test");//根据设置好的映射路径创建连接 var proxy = connection.createHubProxy("test");//根据连接创建我们需要访问的hub代理。test这里是之前创建好的Testhub类 connection.start(function () { //调用服务端方法 proxy.invoke("hello");//调用TestHub中hello方法 }); //为客户端创建方法,这里的sayHi方法提供服务端调用 proxy.on("sayHi", function (msg) { alert(msg); }); }); </script> <meta charset="utf-8" /> </head> <body> </body> </html>