第五節:SignalR大雜燴(與MVC融合、全局的幾個配置、跨域的應用、C/S程序充當Client和Server)


一. 說在前面的話

  本節主要在前面章節的基礎上補充了幾個簡單的知識點,比如:第三方調用通過 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.ConnectionTimeout= 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;

PS:設置消息緩沖區大小

  GlobalHost.Configuration.DefaultMessageBufferSize = 500;

(默認情況下,SignalR 將保留在內存中的每個中心的每個連接的 1000 條消息。 如果使用大型消息時,這可能會造成內存問題,這可以通過減小此值來緩解壓力) 

四. 跨域的應用

   在很多情況下,前后端是分離,客戶端和服務器端並不在一個地址下,比如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 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM