ASP.NET Core SignalR 是微軟開發的一套基於ASP.NET Core的與Web進行實時交互的類庫,它使咱們的應用可以實時的把數據推送給Web客戶端。javascript
自動管理鏈接java
容許同時廣播到全部客戶端git
也能夠廣播到指定的組或者特定的客戶端github
在Github上開源,傳送門(https://github.com/aspnet/signalr)服務器
SignalR 提供了多種鏈接方式,在現代化應用中,WebSocket是最佳的傳輸協議,在客戶端沒法實現WebSocket協議的時候,SignalR就會採起其餘方式,好比Server-Sent或者長輪詢(在ws未出現以前,咱們討論的推拉模式)cookie
SignalR是採用中心客戶端和服務器進行通信。app
中心是一種高級的管道,容許客戶端和服務器之間相互調用方法。異步
中心經過強類型參數傳遞給方法,進行模型綁定async
Clients屬性包含了全部的客戶端鏈接信息,它包含了3個屬性:ide
All 全部客戶端
Caller 進行這次請求的客戶端
Others 排除這次請求客戶端的其餘客戶端
包含了多個方法:
= AllExcept 在指定的鏈接除外的全部鏈接的客戶端上調用方法
Client 在特定鏈接的客戶端上調用方法
Clients 在特定鏈接的客戶端上調用方法
Group 調用指定的組中的一種對全部鏈接方法
GroupExcept 調用中指定的組,除非指定鏈接到的全部鏈接的方法
Groups 調用一種對多個組的鏈接方法
OthersInGroup 調用一種對一組的鏈接,不包括客戶端調用 hub 方法方法
User 調用一種對與特定用戶關聯的全部鏈接方法
Users 調用一種對與指定的用戶相關聯的全部鏈接方法
每一個屬性和方法返回的對象都包含一個SendAsync方法,能夠對客戶端進行調用。
能夠在應用其餘地方經過使用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);
<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>