一. 說在前面的話 本節主要在前面章節的基礎上補充了幾個簡單的知識點,比如:第三方調用通過 GlobalHost.ConnectionManager.GetHubContext<MySpecHub1>();來獲取Hub對象,那麼能不能封裝一下不必每次都這麼獲取呢?再比如SignalR傳輸是否有大小限 ...
一. 說在前面的話
本節主要在前面章節的基礎上補充了幾個簡單的知識點,比如:第三方調用通過 GlobalHost.ConnectionManager.GetHubContext<MySpecHub1>();來獲取Hub對象,那麼能不能封裝一下不必每次都這麼獲取呢?再比如SignalR傳輸是否有大小限制,一下傳輸10w個字能否傳輸成功?最後著重整理一下跨域的各種使用情況,結合C/S程式充當客戶端和伺服器端。
本節內容包括:
①. SignalR與MVC或者WebApi簡單的整合。
②. 全局的幾個配置。
③. 跨域的配置和應用。
④. C/S程式充當客戶端或伺服器端。
二. SignalR與MVC的簡單整合
在前面的章節中我們已經知道,如果要通過控制器中的Action來實現通訊,需要通過 GlobalHost.ConnectionManager.GetHubContext<MySpecHub1>(); 來獲取Hub類,但是每個Action中都這麼獲取,顯得有點麻煩,這裡簡單封裝一下,來便捷開發。
分析:實質在我們在Action中用到的對象無非也就這兩個,IHubConnectionContext<dynamic> Clients 和 IGroupManager Groups ,所以這裡利用繼承的關係簡單的封裝一下,聲明BaseController類,在裡面獲取這兩個對象,然後其它控制器繼承BaseController,並傳入對應的Hub類,這樣在Action中就可以直接使用 Clients和Groups了。
PS:WepAPI程式可以採用下麵類似方式進行封裝。
BaseController代碼展示:
1 /// <summary> 2 /// 整合MVC和SignalR 3 /// </summary> 4 public class BaseController<T> : Controller where T : Hub 5 { 6 public IHubConnectionContext<dynamic> Clients { get; set; } 7 8 public IGroupManager Groups { get; set; } 9 10 public BaseController() 11 { 12 var hub = GlobalHost.ConnectionManager.GetHubContext<T>(); 13 Clients = hub.Clients; 14 Groups = hub.Groups; 15 } 16 }
繼承BaseController的代碼展示:
1 public class HubController : BaseController<MySpecHub1> 2 { 3 4 /// <summary> 5 /// 向所有人發送消息 6 /// </summary> 7 /// <param name="myConnectionId">當前用戶的登錄標記</param> 8 /// <param name="msg">發送的信息</param> 9 public string MySendAll(string myConnectionId, string msg) 10 { 11 //Hub模式 12 Clients.AllExcept(myConnectionId).receiveMsg($"用戶【{myConnectionId}】發來消息:{msg}"); 13 return "ok"; 14 } 15 16 }
三. 全局的幾個配置
這裡的全局配置主要包括:傳輸超時時間、強制關閉時間、WebSocket模式下允許傳輸的數據最大值等等,以下配置代碼可以在Configuration方法中進行配置,可以根據實際業務情況自行選擇配置。
1. 表示客戶端在轉而使用其他傳輸或連接失敗之前應允許連接的時間。預設值為 5 秒。(傳輸超時時間)
GlobalHost.Configuration.TransportConnectTimeout = TimeSpan.FromSeconds(5);
2. 表示連接在超時之前保持打開狀態的時間
GlobalHost.Configuration.TransportConnectTimeout = TimeSpan.FromSeconds(5);
3. 用於表示在連接停止之後引發斷開連接事件之前要等待的時間。 (強制關閉時間)
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(5);
4. 表示兩次發送保持活動消息之間的時間長度。如果啟用,此值必須至少為兩秒。設置為 null 可禁用。
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(2);
5. Websocket模式下允許傳輸數據的最大值,預設為64kb
GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = 64;
四. 跨域的應用
在很多情況下,前後端是分離,客戶端和伺服器端並不在一個地址下,比如APP(這裡指混合開發能使用JS的情況下),這個時候伺服器的SignalR就需要配置允許跨域,這裡有兩種允許跨域的策略,一種是JSONP模式,另外一種是Cors模式。
在Startup類中的Configuration方法中進行配置,代碼如下:
1 public class Startup 2 { 3 public void Configuration(IAppBuilder app) 4 { 5 //配置允許跨域 6 //1. JSONP模式 7 //app.MapSignalR(new HubConfiguration() { EnableJSONP = true }); 8 9 //2. Cors模式(需要安裝Microsoft.Owin.Cors程式集) 10 app.UseCors(CorsOptions.AllowAll).MapSignalR(); 11 } 12 }
註:採用Cors模式的跨域需要安裝:Microsoft.Owin.Cors 程式集,並且上述代碼沒有單獨配置模型路徑,所以採用的是預設路徑“/signalr”。
當然前端代碼也需要進行相應的改寫:
(1). 代理模式的改寫形式:
a. 自動生成代理類代碼需要改寫為 <script src="http://localhost:7080/signalr/hubs"></script> ,localhost:7080,根據實際情況改為實際地址。
b. 需要單獨配置一下Hub的連接路徑, conn.url = "http://localhost:7080/signalr";
以上兩步即為全部改變,其餘位置不需變化。
(2). 非代理模式下的代碼:
非代理模式下就更容易,只需要在hubConnection方法中傳入路徑即可。如下圖:
五. C/S程式充當客戶端
C/S程式(這裡採用控制台)充當客戶端,當然伺服器端必須已經配置了允許跨域,且C/S程式是沒有JS的,所以只能採用非代理模式。
步驟如下:
1:安裝程式集 Microsoft.AspNet.SignalR.Client
2:代碼配置
a. 與伺服器路徑匹配的時候要註意,預設路徑的話,要加上signalr/
b. 如果定義的方法大於一個參數的時候,需要聲明一個類來接收
eg:Proxy.On<Person>("方法名", Person=>
Console.WriteLine("ID{0} Name{1}", Person.ID, Person.Name));
代碼如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 //一. 基礎信息配置 7 //1. 與伺服器路徑進行匹配 8 var conn = new HubConnection("http://localhost:8099/signalr/"); 9 //2. 創建代理類 10 var proxy = conn.CreateHubProxy("MySpecHub1"); 11 12 13 //二. 定義客戶端的方法 14 //特別註意,如果定義的方法大於一個參數的時候,msg的位置需要聲明一個類來接受 15 //1 接受用戶登錄成功後的提示 16 17 proxy.On("LoginSuccessNotice", (msg) => 18 { 19 Console.WriteLine(msg); 20 }); 21 22 //2 接收自己的connectionId 23 proxy.On("ReceiveOwnCid", (msg) => 24 { 25 Console.WriteLine(msg); 26 }); 27 28 //三. 啟動 29 conn.Start().Wait(); 30 31 Console.ReadKey(); 32 33 } 34 }
六. C/S程式充當伺服器端
在很多情況下,我們需要避免使用IIS的性能開銷,或者要將SignalR部署成Windows服務,這個使用就需要使用C/S程式作為伺服器端了。
配置步驟比較簡單,如下:
1. 安裝程式集:Microsoft.AspNet.SignalR.SelfHost 和 Microsoft.Owin.Cors(跨域使用)
2. 添加集線器類MySpecHub1
3. 在Startup中配置允許跨域
4. 編寫啟動代碼
PS:以上步驟2和步驟3在前面章節中已經多次提到過了,這裡指展示一下啟動代碼:
1 static void Main(string[] args) 2 { 3 try 4 { 5 string url = "http://localhost:7080"; 6 using (WebApp.Start<Startup>(url)) 7 { 8 Console.WriteLine("Server running on {0}", url); 9 Console.ReadLine(); 10 } 11 } 12 catch (Exception ex) 13 { 14 Console.WriteLine(ex.Message); 15 } 16 Console.ReadKey(); 17 }
特別註意:如果報System.Reflection.TargetInvocationException was unhandled,直接去bin文件里以管理員身份運行exe程式即可或者以管理員身份運行VS程式然後啟動即可。
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 本人才疏學淺,用郭德綱的話說“我是一個小學生”,如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。