Asp.Net SignalR已經出來好久了,可是一直沒有靜下心來好好看看。昨天花了幾個小時的時間看了下。首先借鑑了官方文檔,如何搭建一個SignalR的Demo。git
參考文章:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.1&tabs=visual-studio github
SignalR地址:https://github.com/aspnet/SignalRredis
因此爲了快速搭建和體驗.Net Core版本的SignalR,我選擇了下載官方的Demo和參考官方給的教程。因此具體的搭建過程我就再也不本文中寫了。瀏覽器
官網給出的DEMO運行以下圖:框架
點擊connect,查看一下network。能夠發現,它在當前瀏覽器支持三種方式。async
並且和.NET Framework版本不一樣的是,新版SignalR中的Hub類型也是蠻豐富的。Demo中給出了 普通Hub,DynamicHub,Hub<T> 三種類型。咱們去看看其中的區別吧。visual-studio
普通Hub網站
查看定義,能夠看到普通Hub中的Clients類型是 IHubCallerClients this
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 定義以下:spa
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,而其餘方法只不過是上層封裝使得代碼更加通俗易懂。
Demo中的其餘例子就再也不演示了。廣播,一對一,一對多,加入組,退出組等基本和以前同樣。這裏在演示一下使用Redis作不一樣實例之間的通訊效果。
首先程序集是不能少的:Microsoft.AspNetCore.SignalR.Redis,而後在Startup中補充代碼:
打開Redis客戶端,使用MONITOR命令監聽一下,從程序啓動,到鏈接,在發送一條廣播消息:hello redis。 redis 監聽結果以下:
因此,PUB/SUB仍是立了大功呢。
這裏用CMD運行了兩個實例,端口分別爲 8881,8882來模擬兩個站點。
演示效果以下:
沒問題的哦,其實仔細想一想,雖然運行了兩個網站實例,可是鏈接信息都保存在同一個Redis上,那確定通訊是木的問題的啦。
只是簡單的運行了一下DEMO,大體瞭解了一下 .Net Core SignalR的表層,至少跑Demo是跑起來了,而且使用Redis也是沒有問題的。不過好像會出現運行一旦時間,程序自動停掉的問題,不知道是否是我電腦的問題。。今天就到這裏吧,但願你們能有所收穫。 本文代碼地址:https://github.com/fanpan26/LayIM.AspNetCore/tree/master/src/LayIM.AspNetCore.Demo/SignalRSamples