.Net Core SignalR 初体验

前言

  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,而其余方法只不过是上层封装使得代码更加通俗易懂。

使用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也是没有问题的。不过好像会出现运行一旦时间,程序自动停掉的问题,不知道是否是我电脑的问题。。今天就到这里吧,但愿你们能有所收获。 本文代码地址:https://github.com/fanpan26/LayIM.AspNetCore/tree/master/src/LayIM.AspNetCore.Demo/SignalRSamples

相关文章
相关标签/搜索