zoukankan      html  css  js  c++  java
  • ASP.NET Core SignalR

    ASP.NET Core SignalR 是微软开发的一套基于ASP.NET Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给Web客户端。

    功能

    • 自动管理连接

    • 允许同时广播到所有客户端

    • 也可以广播到指定的组或者特定的客户端

    • 在Github上开源,传送门(https://github.com/aspnet/signalr)

    SignalR 提供了多种连接方式,在现代化应用中,WebSocket是最佳的传输协议,在客户端无法实现WebSocket协议的时候,SignalR就会采取其他方式,比如Server-Sent或者长轮询(在ws未出现之前,我们讨论的推拉模式)

    中心 Hubs

    SignalR是采用中心客户端和服务器进行通讯。

    中心是一种高级的管道,允许客户端和服务器之间相互调用方法。

    中心通过强类型参数传递给方法,进行模型绑定

    Hubs.Clients

    Clients属性包含了所有的客户端连接信息,它包含了3个属性:

    • All 所有客户端

    • Caller 进行此次请求的客户端

    • Others 排除此次请求客户端的其他客户端

    包含了多个方法:

    • = AllExcept 在指定的连接除外的所有连接的客户端上调用方法

    • Client 在特定连接的客户端上调用方法

    • Clients 在特定连接的客户端上调用方法

    • Group 调用指定的组中的一种对所有连接方法

    • GroupExcept 调用中指定的组,除非指定连接到的所有连接的方法

    • Groups 调用一种对多个组的连接方法

    • OthersInGroup 调用一种对一组的连接,不包括客户端调用 hub 方法方法

    • User 调用一种对与特定用户关联的所有连接方法

    • Users 调用一种对与指定的用户相关联的所有连接方法

    每个属性和方法返回的对象都包含一个SendAsync方法,可以对客户端进行调用。

    HubContext

    可以在应用其他地方通过使用IHubContext,达到调用Hub的目的。

    两种协议

    • 文本协议:JSON

    • 二进制协议:MessagePack(https://msgpack.org/)

    MessagePack类似于JSON,但传输比JSON更快,数据大小比JSON更小

    服务器事项

    • 创建的Hub必须继承Microsoft.AspNetCore.SignalR.Hub,Hub类已经包含了管理连接、组和发送接收消息的属性及事件

    • 在Hub中使用的方法应该尽量使用异步的方式,因为SignalR在发送和接收消息的时候使用的是异步方法。

    • 在Startup.ConfigureServices中通过services.AddSignalR对SignalR进行注册

    • 在Startup.Configure中通过app.UseSignalR方法对Hub路由进行配置

    代码解析

    微软官方示范(https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-2.1&tabs=visual-studio)中的ChatHub:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
     
    namespace SignalRChat.Hubs
    {
        public class ChatHub : Hub
        {
            //服务端方法
            public async Task SendMessage(string user, string message)
            {
                //ReceiveMessage 为客户端方法,让所有客户端调用这个方法
                await Clients.All.SendAsync("ReceiveMessage", user, message);
            }
        }
    }
    

     

    上述代码为当收到客户端发来的SendMessage请求后(发送聊天信息),我们把消息发送到所有客户端,让他们调用自身的ReceiveMessage方法。

    用户标识

    通常情况下,在用户进行连接后,Connection会保存用户的用户标识,以便对特定用户进行发送消息。

    可以实现IUserIdProvider来自定义获取用户的方法,例如:

    public class CustomUserIdProvider : IUserIdProvider
    {
        public virtual string GetUserId(HubConnectionContext connection)
        {
            return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
        }
    }
    

     

    在Startup.ConfigureServices中注册:

    services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
    

      

     

    Client的方法

    T All { get; } 

    相当于持久连接中的 Broadcast。

    T AllExcept(params string[] excludeConnectionIds);

    给排除本人所有人发送消息。

    T Client(string connectionId);

    跟Send操作就是一样的了。

    T Clients(IList<string> connectionIds);

    和Send操作的重载方法一样,可以给一批指定的人发送。

    T Group(string groupName, params string[] excludeConnectionIds);

    给房间中的指定人发送消息: Clients.Group("room1", "asdfasdfads");

    T Groups(IList<string> groupNames, params string[] excludeConnectionIds);

    给房间列表中的指定人发送消息; 【天然的聊天室功能】

    T User(string userId);

    这个和Client是有区别的。 这个userId => this.Context.Request.User.Identity.Name 【form验证】

    cookie中间件来做到singlar的身份验证。

      userId 是你自己定义的一个标识。

    T Users(IList<string> userIds);

    客户端JS使用方法

    <script src="~/lib/signalr/signalr.js"></script>
        <script type="text/javascript">
            const connection = new signalR.HubConnectionBuilder()
                .withUrl("/myChatHub")
                .configureLogging(signalR.LogLevel.Information)
                .build();
            connection.start().catch(err => console.error(err.toString()));
            //定义方法使用connection.on方法来接收返回数据
            connection.on("SendMessage", (user, message) => {
                const encodedMsg = user + " 说:" + message;
                const li = document.createElement("li");
                li.textContent = encodedMsg;
                document.getElementById("messagesList").appendChild(li);
            });
    
            document.getElementById("sendBtn").addEventListener("click", function () {
                var user = document.getElementById('userName').value;
                var message = document.getElementById('message').value;
                //从客户端中调用在此调用之前在自定义Hub定义的SendMessage方法
                connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
                document.getElementById('message').value = "";
            });
    </script>
    

      

  • 相关阅读:
    Docker 实战(2)- 在 Jenkins 容器上的搭建持续集成环境和完成自动化测试
    Docker
    Jenkins(9)- 汉化 Jenkins 网站
    Docker 实战(1)- 使用 Jenkins 镜像创建容器,并搭建 Python + Pytest +Allure 的自动化测试环境
    Python
    Docker
    Linux
    Docker(20)- docker rmi 命令详解
    Docker(19)- docker pause/unpause 命令详解
    Docker(18)- docker kill 命令详解
  • 原文地址:https://www.cnblogs.com/zhurunlai/p/9582737.html
Copyright © 2011-2022 走看看