在持久性連接的基礎上,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>