ASP.NET Core SignalR:集線器Hubs
一、什麼是集線器hubs
通過SignalR的集線器hubs中定義的方法,伺服器可以呼叫連線中的客戶端定義的方法,而客戶端也可以呼叫伺服器端集線器中定義的方法。SignalR負責實現了客戶端和伺服器之間的實時通訊。
二、配置SignalR的hubs
SignalR通過在Startup.ConfigureServices中呼叫services.AddSignalR()來配置中介軟體服務。
services.AddSignalR()
將 SignalR 功能新增到 ASP.NET Core 應用程式時,通過在Startup.Configure方法中呼叫app.UseSignalR來設定 SignalR 路由。
app.UseSignalR(routes => { routes.MapHub<BaseHub>("/Hub"); });
三、建立集線器Hubs
通過繼承Hub類來建立集線器類,並新增public修飾的方法。可以通過特性[HubMethodName]來修改方法的名稱。
public async Task SendMessage(string user,string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); }
注意:
- 客戶端只能呼叫集線器類中定義的public的方法。
- 每次客戶端訪問伺服器的集線器類的時候都是在新的物件例項上執行的,所以不能將狀態儲存在集線器類中。
- SignalR的程式碼是非同步模式的,所以集線器中的方法也都是非同步的。
四、引數和返回型別
將集線器類和客戶端接收程式碼改為如下所示:
public class paramsEntity { public string user { get; set; } public string message { get; set; } } public async Task SendMessage(paramsEntity param) { await Clients.All.SendAsync("ReceiveMessage", param); }
//接收伺服器端訊息ReceiveMessage的處理程式 connection.on("ReceiveMessage", function (param) { if (param.user) $('#content').append(param.user + ":"); if (param.message) $('#content').append(param.message + ":"); }); //傳送訊息至伺服器端SendMessage方法 connection.invoke("SendMessage", { user, message }).catch(function (err) { return console.error(err.toString()); });
通過執行可以發現,SignalR會通過序列化和反序列化來處理複雜的引數和返回型別。如果客戶端傳遞的引數和伺服器端不一致會導致方法無法被匹配到而報錯以下錯誤。
Microsoft.AspNetCore.SignalR.HubException: Failed to invoke 'SendMessage' due to an error on the server.
所以使用自定義物件作為引數更加的靈活多變。
五、Hub的物件
1、Context
Hub類具有一個上下文Context,包含連線中的以下屬性以及方法。
屬性 | 描述 |
ConnectionId | 獲取由 SignalR 分配的連線的唯一 ID。每個連線都有一個連線 ID |
UserIdentifier | 獲取使用者識別符號。 預設情況下,SignalR 使用ClaimTypes.NameIdentifier 與連線ClaimsPrincipal 關聯的作為使用者識別符號。 |
User | 獲取與ClaimsPrincipal 當前使用者關聯的。 |
Items | 獲取可用於在此連線的範圍內共享資料的鍵/值集合。資料可以儲存在此集合中,它將在不同的集線器方法呼叫中持久儲存。 |
Features | 獲取連線上的可用功能的集合。目前,在大多數情況下不需要此集合,因此不會對其進行詳細介紹。 |
ConnectionAborted | 獲取一個CancellationToken ,它將在連線中止時通知。 |
方法 | 描述 |
GetHttpContext | 返回連線HttpContext 的null ,如果連線不與 HTTP 請求關聯,則為。對於 HTTP 連線,可以使用此方法來獲取 HTTP 標頭和查詢字串等資訊。 |
Abort | 中止連線。 |
2、Clients
Hub類的Clients屬性包含伺服器和客戶端之間通訊的方法和屬性。
屬性 | 描述 |
All | 在所有連線的客戶端上呼叫方法 |
Caller | 在呼叫集線器方法的客戶端上呼叫方法 |
Others | 在所有連線的客戶端上呼叫方法,但呼叫方法的客戶端除外 |
方法 | 描述 |
AllExcept | 在所有連線的客戶端(指定的連線除外)上呼叫方法 |
Client | 在特定連線的客戶端上呼叫方法 |
Clients | 在多個特定連線的客戶端上呼叫方法 |
Group | 對指定組中的所有連線呼叫方法 |
GroupExcept | 對指定組中的所有連線呼叫方法,指定的連線除外 |
Groups | 在多組連線上呼叫方法 |
OthersInGroup | 對一組連線呼叫方法,而不包括呼叫該集線器方法的客戶端 |
User | 對與特定使用者關聯的所有連線呼叫方法 |
Users | 對與指定使用者相關聯的所有連線呼叫方法 |
表中的每個屬性或方法都返回一個SendAsync
包含方法的物件。 SendAsync
方法允許你提供要呼叫的客戶端方法的名稱和引數。
六、強型別的hub
使用SendAsync的時候需要傳入字串來指定呼叫客戶端的方法,這就會導致拼寫錯誤等問題引發程式執行錯誤。
通過使用強型別Hub<T>將客戶端的方法約定為介面,這樣Hub的Clients的將會禁用Sendasync方法,而只能呼叫我們約定的介面方法。
public interface IHub { Task ReceiveMessage(string user, string message); Task ReceiveMessage(string message); }
public class BaseHub : Hub<IHub> { public async Task SendMessage(string user, string message) { await Clients.All.ReceiveMessage(user, message); } }
七、處理連線事件
SignalR的hub提供OnConnectedAsync
和OnDisconnectedAsync
虛擬方法來管理和跟蹤連線。 重寫OnConnectedAsync
虛擬方法,以便在客戶端連線到集線器時執行操作,如將其新增到組。
public override async Task OnConnectedAsync() { await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users"); await base.OnConnectedAsync(); }
重寫OnDisconnectedAsync
虛擬方法,以便在客戶端斷開連線時執行操作。 如果客戶端故意斷開連線(例如connection.stop()
,通過呼叫),則exception
引數將為null
。 但是,如果客戶端由於錯誤(例如網路故障)而斷開連線,則exception
引數將包含描述失敗的異常。
public override async Task OnDisconnectedAsync(Exception exception) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users"); await base.OnDisconnectedAsync(exception); }
&n