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>

  

 


免責聲明!

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



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