SignalR 提供了多種連接方式,在現(xiàn)代化應(yīng)用中,WebSocket是最佳的傳輸協(xié)議,在客戶端無法實(shí)現(xiàn)WebSocket協(xié)議的時(shí)候,SignalR就會(huì)采取其他方式,比如Server-Sent或者長(zhǎng)輪詢(在ws未出現(xiàn)之前,我們討論的推拉模式)
SignalR是采用中心客戶端和服務(wù)器進(jìn)行通訊。
中心是一種高級(jí)的管道,允許客戶端和服務(wù)器之間相互調(diào)用方法。
中心通過強(qiáng)類型參數(shù)傳遞給方法,進(jìn)行模型綁定
Clients屬性包含了所有的客戶端連接信息,它包含了3個(gè)屬性:
All
所有客戶端Caller
進(jìn)行此次請(qǐng)求的客戶端Others
排除此次請(qǐng)求客戶端的其他客戶端AllExcept
在指定的連接除外的所有連接的客戶端上調(diào)用方法Client
在特定連接的客戶端上調(diào)用方法Clients
在特定連接的客戶端上調(diào)用方法Group
調(diào)用指定的組中的一種對(duì)所有連接方法GroupExcept
調(diào)用中指定的組,除非指定連接到的所有連接的方法Groups
調(diào)用一種對(duì)多個(gè)組的連接方法OthersInGroup
調(diào)用一種對(duì)一組的連接,不包括客戶端調(diào)用 hub 方法方法User
調(diào)用一種對(duì)與特定用戶關(guān)聯(lián)的所有連接方法Users
調(diào)用一種對(duì)與指定的用戶相關(guān)聯(lián)的所有連接方法每個(gè)屬性和方法返回的對(duì)象都包含一個(gè)SendAsync
方法,可以對(duì)客戶端進(jìn)行調(diào)用。
可以在應(yīng)用其他地方通過使用IHubContext,達(dá)到調(diào)用Hub的目的。
MessagePack類似于JSON,但傳輸比JSON更快,數(shù)據(jù)大小比JSON更小
Microsoft.AspNetCore.SignalR.Hub
,Hub類已經(jīng)包含了管理連接、組和發(fā)送接收消息的屬性及事件Startup.ConfigureServices
中通過services.AddSignalR
對(duì)SignalR進(jìn)行注冊(cè)Startup.Configure
中通過app.UseSignalR
方法對(duì)Hub路由進(jìn)行配置微軟官方示范中的ChatHub:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace SignalRChat.Hubs
{
public class ChatHub : Hub
{
//服務(wù)端方法
public async Task SendMessage(string user, string message)
{
//ReceiveMessage 為客戶端方法,讓所有客戶端調(diào)用這個(gè)方法
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
上述代碼為當(dāng)收到客戶端發(fā)來的SendMessage
請(qǐng)求后(發(fā)送聊天信息),我們把消息發(fā)送到所有客戶端,讓他們調(diào)用自身的ReceiveMessage
方法。
通常情況下,在用戶進(jìn)行連接后,Connection會(huì)保存用戶的用戶標(biāo)識(shí),以便對(duì)特定用戶進(jìn)行發(fā)送消息。
可以實(shí)現(xiàn)IUserIdProvider
來自定義獲取用戶的方法,例如:
public class CustomUserIdProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
}
}
在Startup.ConfigureServices
中注冊(cè):
services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
分組類似于聊天室中的每個(gè)房間,通過分組,我們可以給特定小組發(fā)送消息。
用戶標(biāo)識(shí)和組名稱都是區(qū)分大小寫的。
小程序因?yàn)闊o法直接使用websocket,所以無法使用signalR.js,你可以試著把signalR.js中的webcosket使用部分換成wx.xxSocketxxx。
在參考了算神的代碼后,歸了一個(gè)小類庫,方便大家使用,源碼較長(zhǎng),我放到了github上,點(diǎn)擊【傳送門】進(jìn)入。
在要使用的頁面上:
///引入這個(gè)類庫
var signalR = require('../../lib/signalr/signalr.js')
///實(shí)例化一個(gè)對(duì)象
let _client = new signalR.signalR();
這是為了讓小程序收到SignalR的消息之后進(jìn)行回調(diào)
callMethods(methods, args) {
console.log(methods, args);
let self = this;
switch (methods) {
case 'sayHello':
self.sayHello(args[0]);
break;
}
},
例子里有一個(gè)sayHello方法,我們用字符串作為key。
_client.connection(url, methodMapping);
_client.call(methodName, args, success, fail)