Asp.Net Core API 和 WinForm 的 SignalR 例子

什么是 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;
          }
      }
  }

Demo下载

原文地址:https://www.cnblogs.com/SuperDust/p/12769647.html