什么是Asp.Net Core SignalR
Asp.Net Core SignalR 是微軟開發的一套基於Asp.Net Core的與Web進行實時交互的類庫,它使我們的應用能夠實時的把數據推送給Web客戶端。
功能
- 自動管理連接
- 允許同時廣播到所有客戶端
- 也可以廣播到指定的組或者特定的客戶端
- 在Github上開源,傳送門
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
MessagePack類似於JSON,但傳輸比JSON更快,數據大小比JSON更小
服務器事項
- 創建的Hub必須繼承
Microsoft.AspNetCore.SignalR.Hub
,Hub類已經包含了管理連接、組和發送接收消息的屬性及事件 - 在Hub中使用的方法應該盡量使用異步的方式,因為SignalR在發送和接收消息的時候使用的是異步方法。
- 在
Startup.ConfigureServices
中通過services.AddSignalR
對SignalR進行注冊 - 在
Startup.Configure
中通過app.UseSignalR
方法對Hub路由進行配置
代碼解析
微軟官方示范中的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>();
Group 分組
分組類似於聊天室中的每個房間,通過分組,我們可以給特定小組發送消息。
用戶標識和組名稱都是區分大小寫的。
微信小程序與SignalR交互
小程序因為無法直接使用websocket,所以無法使用signalR.js,你可以試着把signalR.js中的webcosket使用部分換成wx.xxSocketxxx。
在參考了算神的代碼后,歸了一個小類庫,方便大家使用,源碼較長,我放到了github上,點擊【傳送門】進入。
如何使用
調用類庫
在要使用的頁面上:
///引入這個類庫
var signalR = require('../../lib/signalr/signalr.js')
///實例化一個對象
let _client = new signalR.signalR();
創建 一個映射方法
這是為了讓小程序收到SignalR的消息之后進行回調
callMethods(methods, args) {
console.log(methods, args);
let self = this;
switch (methods) {
case 'sayHello':
self.sayHello(args[0]);
break;
}
},
例子里有一個sayHello方法,我們用字符串作為key。
進行連接
_client.connection(url, methodMapping);
- url : signalR服務器
- methodMapping : 方法和字符串之間的Mapping
調用SignalR方法
_client.call(methodName, args, success, fail)
- methodName:遠程方法名
- args:參數,這里注意一定要數組格式
- success:調用成功后的回調
- fail:失敗后的回調
寫在最后
最近真的忙,忙成一道閃電,正好遇到這個問題隨之記錄下。類庫可能並不完善,你可以在github上提issue,我會跟進的,有好的修改方式,你也可以PR我。