定义一个Hub
cs
using Microsoft.AspNetCore.SignalR;
namespace Beatrane.Connect.Blazor
{
public class DeviceHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public async Task UpdateOnlineStatus(string deviceId, string status)
{
await Clients.All.SendAsync("OnlineStatusUpdated", deviceId, status);
}
}
}
程序初始化的时候要注册这个Hub
cs
const string hubsPrefix = "/hubs";
app.MapGroup(hubsPrefix).MapHub<DeviceHub>("/devicehub");
在 Blazor 的一个页面接收来自客户端 Winform 的消息
cs
private HubConnection? _hubConnection;
private string? _deviceId;
private string? _status;
protected override async Task OnInitializedAsync()
{
try
{
var url = NavigationManager.ToAbsoluteUri("/hubs/devicehub");
_hubConnection = new HubConnectionBuilder()
.WithUrl(url)
.Build();
_hubConnection.On<string, string>("OnlineStatusUpdated", async (deviceId, status) =>
{
_deviceId = deviceId;
_status = status;
await InvokeAsync(StateHasChanged);
});
_hubConnection.Closed += async (error) =>
{
Console.WriteLine("Connection closed: " + error);
await Task.Delay(new Random().Next(0, 5) * 1000);
await _hubConnection.StartAsync();
};
await _hubConnection.StartAsync();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
注意以下,下面说的是一个坑点,SignalR 的包, VS 默认会建议你安装
cs
Microsoft.AspNetCore.SignalR.Client.Core
但实际你要安装的是
cs
Microsoft.AspNetCore.SignalR.Client
不然会少一个扩展类,没有 WithUrl方法可以用了
那么上面Blazor服务端的事就做完了,非常简单。下面是Winform 客户端。因为咱使用的是 https,所以还有个连接时证书验证的问题。这里使用 clientHandler.ServerCertificateCustomValidationCallback = ValidateServerCertificate 直接返回 True 。等真的需要验证了再改写 ValidateServerCertificate 方法的逻辑
cs
using Microsoft.AspNetCore.SignalR.Client;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
private HubConnection _hubConnection;
public Form1()
{
InitializeComponent();
}
private bool ValidateServerCertificate(HttpRequestMessage message, X509Certificate2? certificate, X509Chain? chain, SslPolicyErrors errors)
{
return true;
}
private async void button1_Click(object sender, EventArgs e)
{
try
{
if (_hubConnection is { State: HubConnectionState.Connected })
{
await _hubConnection.InvokeAsync(@"UpdateOnlineStatus", Guid.NewGuid().ToString(), "Online");
}
else
{
var url = @"https://localhost:5001/hubs/devicehub";
_hubConnection = new HubConnectionBuilder()
.WithUrl(url, options =>
{
options.HttpMessageHandlerFactory = handler =>
{
if (handler is HttpClientHandler clientHandler)
{
clientHandler.ServerCertificateCustomValidationCallback = ValidateServerCertificate;
}
return handler;
};
})
.WithAutomaticReconnect()
.Build();
_hubConnection.ServerTimeout = TimeSpan.FromSeconds(5);
await _hubConnection.StartAsync();
await _hubConnection.InvokeAsync(@"UpdateOnlineStatus", Guid.NewGuid().ToString(), "Online");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
这个时候就可以把两端的程序跑来做验证了
每点击一次 Button1 ,Blazor 的网页端就会收到新的 guid。如此,通信便完成了