什么是 SignalR?
ASP.NET Core SignalR 是一個開源庫,它簡化了向應用程序添加實時 web 功能的功能。 實時 Web 功能使服務器端代碼能夠即時將內容推送到客戶端。
官方列舉的SignalR適用場景:
- 需要從服務器進行高頻率更新的應用。 示例包括游戲、社交網絡、投票、拍賣、地圖和 GPS 應用。
- 儀表板和監視應用。 示例包括公司儀表板、即時銷售更新或旅行警報。
- 協作應用。 協作應用的示例包括白板應用和團隊會議軟件。
- 需要通知的應用。 社交網絡、電子郵件、聊天、游戲、旅行警報和很多其他應用都需使用通知。
創建SignalR服務端Asp.Net Core API 這參考了Blog系統的寫法
引用SignalR序列化的包
Install-Package Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson -Version 3.1.3
Startup類ConfigureServices方法里注冊SignalR服務
services.AddSignalR().AddNewtonsoftJsonProtocol();
創建SignalR的Hub定義消息,分別是IChatClient和ChatHub
IChatClient
public interface IChatClient
{
/// <summary>
/// SignalR接收信息
/// </summary>
/// <param name="message">信息內容</param>
/// <returns></returns>
Task ReceiveMessage(object message);
/// <summary>
/// SignalR接收信息
/// </summary>
/// <param name="user">指定接收客戶端</param>
/// <param name="message">信息內容</param>
/// <returns></returns>
Task ReceiveMessage(string user, string message);
Task ReceiveUpdate(object message);
}
ChatHub
public class ChatHub : Hub<IChatClient>
{
/// <summary>
/// 向指定群組發送信息
/// </summary>
/// <param name="groupName">組名</param>
/// <param name="message">信息內容</param>
/// <returns></returns>
public async Task SendMessageToGroupAsync(string groupName, string message)
{
await Clients.Group(groupName).ReceiveMessage(message);
}
/// <summary>
/// 加入指定組
/// </summary>
/// <param name="groupName">組名</param>
/// <returns></returns>
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
/// <summary>
/// 退出指定組
/// </summary>
/// <param name="groupName">組名</param>
/// <returns></returns>
public async Task RemoveFromGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
/// <summary>
/// 向指定成員發送信息
/// </summary>
/// <param name="user">成員名</param>
/// <param name="message">信息內容</param>
/// <returns></returns>
public async Task SendPrivateMessage(string user, string message)
{
await Clients.User(user).ReceiveMessage(message);
}
/// <summary>
/// 當連接建立時運行
/// </summary>
/// <returns></returns>
public override Task OnConnectedAsync()
{
//TODO..
return base.OnConnectedAsync();
}
/// <summary>
/// 當鏈接斷開時運行
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
public override Task OnDisconnectedAsync(System.Exception ex)
{
//TODO..
return base.OnDisconnectedAsync(ex);
}
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
//定於一個通訊管道,用來管理我們和客戶端的連接
//1、客戶端調用 WinFormsApp,就像訂閱
//2、服務端主動向客戶端發送數據,名字千萬不能錯
//3、客戶端再通過 ReceiveUpdate ,來接收
public async Task WinFormsApp(string name, string msg)
{
await Clients.All.ReceiveUpdate($"接收到{name}的消息,消息內容:{msg}");
}
}
創建中間件SignalRSendMildd和MiddlewareHelpers
SignalRSendMildd
/// <summary>
/// 中間件
/// </summary>
public class SignalRSendMildd
{
/// <summary>
///上下文
/// </summary>
private readonly RequestDelegate _next;
private readonly IHubContext<ChatHub> _hubContext;
/// <summary>
///注入上下文
/// </summary>
/// <param name="next"></param>
/// <param name="hubContext"></param>
public SignalRSendMildd(RequestDelegate next, IHubContext<ChatHub> hubContext)
{
_next = next;
_hubContext = hubContext;
}
/// <summary>
/// SignalR過濾
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task InvokeAsync(HttpContext context)
{
await _next(context);
}
}
MiddlewareHelpers
public static class MiddlewareHelpers
{
/// <summary>
/// SignalR中間件
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseSignalRSendMildd(this IApplicationBuilder app)
{
return app.UseMiddleware<SignalRSendMildd>();
}
}
Startup類Configure方法里調用中間件設置SignalR服務路由
// signalr
app.UseSignalRSendMildd();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ChatHub>("/signalr/chatHub");
});
創建SignalR客戶端發送消息返回發送的消息內容,這里客戶端用winform
這是界面
引用SignalR的包
Install-Package Microsoft.AspNetCore.SignalR.Client
public partial class WinFormsApp : Form
{
private HubConnection connection;
public WinFormsApp()
{
InitializeComponent();
SignalRConnection();
}
public async void SignalRConnection()
{
connection = new HubConnectionBuilder()
.WithUrl("http://localhost:5000/signalr/chatHub")
.Build();
await connection.StartAsync();
connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0, 5) * 1000);
await connection.StartAsync();
};
}
private async void button1_Click(object sender, EventArgs e)
{
try
{
await connection.InvokeAsync("WinFormsApp", "SignalRClient", this.textBox1.Text);
connection.On<object>("ReceiveUpdate", (message) =>
{
this.Invoke(new Action(() =>
{
this.textBox2.Text = message.ToString();
}));
});
}
catch (Exception ex)
{
this.textBox2.Text = ex.Message;
}
}
}