Asp.Net Core API 和 WinForm 的 SignalR 例子
什么是 SignalR?
ASP.NET Core SignalR 是一个开源库,它简化了向应用程序添加实时 web 功能的功能。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。
官方列举的SignalR适用场景:
- 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
- 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
- 协作应用。 协作应用的示例包括白板应用和团队会议软件。
- 需要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。
创建SignalR服务端Asp.Net Core API
引用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;
}
}
}