1. 程式人生 > >.Net Core SignalR 初體驗

.Net Core SignalR 初體驗

前言

  Asp.Net SignalR已經出來很久了,但是一直沒有靜下心來好好看看。昨天花了幾個小時的時間看了下。首先借鑑了官方文件,如何搭建一個SignalR的Demo。

  所以為了快速搭建和體驗.Net Core版本的SignalR,我選擇了下載官方的Demo和參考官方給的教程。所以具體的搭建過程我就不再本文中寫了。

體驗效果

  官網給出的DEMO執行如下圖:

   

  點選connect,檢視一下network。可以發現,它在當前瀏覽器支援三種方式。

  

  而且和.NET Framework版本不同的是,新版SignalR中的Hub型別也是蠻豐富的。Demo中給出了 普通Hub,DynamicHub,Hub<T> 三種類型。我們去看看其中的區別吧。

  普通Hub

檢視定義,可以看到普通Hub中的Clients型別是 IHubCallerClients 

namespace Microsoft.AspNetCore.SignalR
{
    //
    // 摘要:
    //     A base class for a SignalR hub.
    public abstract class Hub : IDisposable
    {
        protected Hub();

        //
        // 摘要:
        //     Gets or sets an object that can be used to invoke methods on the clients connected
        //     to this hub.
        public IHubCallerClients Clients { get; set; }
        //
        // 摘要:
        //     Gets or sets the hub caller context.
        public HubCallerContext Context { get; set; }
        //
        // 摘要:
        //     Gets or sets the group manager.
        public IGroupManager Groups { get; set; }

        //
        public void Dispose();
        //
        // 摘要:
        //     Called when a new connection is established with the hub.
        //
        // 返回結果:
        //     A System.Threading.Tasks.Task that represents the asynchronous connect.
        public virtual Task OnConnectedAsync();
        //
        // 摘要:
        //     Called when a connection with the hub is terminated.
        //
        // 返回結果:
        //     A System.Threading.Tasks.Task that represents the asynchronous disconnect.
        public virtual Task OnDisconnectedAsync(Exception exception);
        //
        // 摘要:
        //     Releases all resources currently used by this Microsoft.AspNetCore.SignalR.Hub
        //     instance.
        //
        // 引數:
        //   disposing:
        //     true if this method is being invoked by the Microsoft.AspNetCore.SignalR.Hub.Dispose
        //     method, otherwise false.
        protected virtual void Dispose(bool disposing);
    }
}

  IHubCallerClients 定義如下:

  public interface IHubCallerClients : IHubCallerClients<IClientProxy>, IHubClients<IClientProxy>
    {
    }

  而框架又給IClientProxy增加了擴充套件方法:SendAsync

  所以在普通Hub中,定義客戶端方法的時候,需要把方法名當作引數傳入SendAsync方法中。例如如下程式碼:

 public Task Send(string message)
        {
            return Clients.All.SendAsync("Receive", $"{Context.ConnectionId}: {message}");
        }

  DynamicHub

DynamicHub我是比較喜歡的,因為他和 Framework版的是一樣(或者說看起來是一樣的)的。動態Hub我們就可以不必拘泥於只能呼叫SendAsync方法了。例如:

  public Task SendToOthers(string message)
        {
            return Clients.Others.ThisIsMyReceiveMethod($"{Context.ConnectionId}: {message}");
        }

  DynamicHub的Clients型別為:DynamicHubClients ,它的內部變數全都是dynamic型別的。

  

  Hub<T>

泛型Hub就把規約交給開發者制定。在Demo中 Hub<IChatClient> 中的IChatClient介面定義了Receive方法,因此Clients中的物件可以呼叫Receive方法。同理,我們可以根據業務需要定義自己的方法。至少從程式碼上看會顯得更加通俗易懂一些。比如:

 public interface IChatClient
    {
        Task Receive(string message);
        Task LoginSuccess(long userId);
    }
     public Task Login(long userId)
        {
            return Clients.Caller.LoginSuccess(userId);
        }

  其實從程式碼上來看的話,他們都是Hub,只不過是不同的擴充套件實現而已。而泛型Hub不過是使用者自定義泛型介面,而預設Hub中的預設泛型介面為:IClientProxy.所以看到這裡,如果我就想使用原生的Hub而又想自定義方法怎麼辦呢?很簡單,加擴充套件就可以了。

  為什麼自己加就可以呢,其實 SendAsync 就是擴充套件方法,它內部也是呼叫了SendCoreAsync方法。於是乎,寫下自己的擴充套件方法,那這樣子就很靈活了。我們把method引數去掉,直接寫死試試:

  public static Task LoginAsync(this IClientProxy clientProxy, string message, CancellationToken cancellationToken = default(CancellationToken))
        {
            return clientProxy.SendCoreAsync("LoginSuccess", new object[] { message}, cancellationToken);
        }

  其實說白了,這個擴充套件方法還是需要傳入method引數的,只不過封裝了一層(似乎感覺這麼做有意義嗎?哈哈,還是老老實實用泛型吧),那麼我們在去看Hub中的方法,修改Send方法如下:

  public Task Send(string message)
        {
            return Clients.All.LoginAsync($"{Context.ConnectionId}: {message}");
        }

  是不是這樣子就實現了自己自定義方法了呢?個人覺得這麼寫還繞了一圈,不如用泛型或者Dynamic了。

  執行一下,看看效果:

  

  其實我也是抱著試試的態度,沒想到還真是這樣,和新方法就是SendCoreAsync,而其他方法只不過是上層封裝使得程式碼更加通俗易懂。

使用Redis

  Demo中的其他例子就不再演示了。廣播,一對一,一對多,加入組,退出組等基本和之前一樣。這裡在演示一下使用Redis做不同例項之間的通訊效果。

  首先程式集是不能少的:Microsoft.AspNetCore.SignalR.Redis,然後在Startup中補充程式碼:

  

  開啟Redis客戶端,使用MONITOR命令監聽一下,從程式啟動,到連線,在傳送一條廣播訊息:hello redis。  redis 監聽結果如下:

  

  所以,PUB/SUB還是立了大功呢。

  這裡用CMD運行了兩個例項,埠分別為 8881,8882來模擬兩個站點。

  

  演示效果如下:

   沒問題的哦,其實仔細想想,雖然運行了兩個網站例項,但是連線資訊都儲存在同一個Redis上,那肯定通訊是木的問題的啦。

總結

  只是簡單的運行了一下DEMO,大致瞭解了一下 .Net Core SignalR的表層,至少跑Demo是跑起來了,並且使用Redis也是沒有問題的。不過好像會出現執行一旦時間,程式自動停掉的問題,不知道是不是我電腦的問題。。今天就到這裡吧,希望大家能有所收穫。