翼度科技»论坛 编程开发 .net 查看内容

ASP.NET Core实时库SignalR简单应用

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
一、什么是SignalR:

SignalR 是用于构建需要实时用户交互或实时数据更新的Web 应用程序的一个开放源代码.NET 库。不仅仅用在Web应用中,后面会讲到它的应用范围。它简化了简化了构建实时应用程序的过程,包括ASP.NET Server库和JavaScript Client库,以便管理Client与Server连接并将内容更新推送给Client。
SignalR可用于需要实时刷新获取后台数据的程序。常用的场景范围有:社交应用程序、 多用户游戏、 业务协作和新闻,天气或财务更新应用程序等等。

二、关于WebSocket知识拓展:

在传统的HTTP中,只能客户端主动向服务器端发起请求,服务器端无法主动向客户端发送消息。有的业务场景下,我们需要服务器端主动向客户端发送消息,比如Web聊天室、OA系统、站内消息等。
为了实现服务器端向客户端推送消息,在2008年诞生了WebSocket协议,并且该协议在2011年成为国际标准。目前所有的主流浏览器都已经支持WebSocket协议。WebSocket基于TCP(transmission control protocol,传输控制协议),支持二进制通信,因此通信效率非常高,它可以让服务器处理大量的并发WebSocket连接;WebSocket是双工通信,因此服务器可以高效地向客户端推送消息。
三、建立SignalR服务端:

项目架构:


集线器服务定义:
  1.   /// <summary>
  2.     /// 定义集线器
  3.     /// </summary>
  4.     public class MyHub : Hub
  5.     {
  6.         /// <summary>
  7.         /// 用户字典
  8.         /// </summary>
  9.         private static Dictionary<string, string> dictUsers = new Dictionary<string, string>();
  10.         /// <summary>
  11.         /// 建立连接回调
  12.         /// </summary>
  13.         /// <returns></returns>
  14.         public override Task OnConnectedAsync()
  15.         {
  16.             Console.WriteLine($"ID:{Context.ConnectionId} 已连接");
  17.             return base.OnConnectedAsync();
  18.         }
  19.         /// <summary>
  20.         /// 断开连接回调
  21.         /// </summary>
  22.         /// <param name="exception"></param>
  23.         /// <returns></returns>
  24.         public override Task OnDisconnectedAsync(Exception? exception)
  25.         {
  26.             Console.WriteLine($"ID:{Context.ConnectionId} 已断开");
  27.             return base.OnDisconnectedAsync(exception);
  28.         }
  29.         /// <summary>
  30.         /// 登录功能,将用户ID和ConntectionId关联起来
  31.         /// </summary>
  32.         /// <param name="userId"></param>
  33.         public void Login(string userId)
  34.         {
  35.             if (!dictUsers.ContainsKey(userId))
  36.             {
  37.                 dictUsers[userId] = Context.ConnectionId;
  38.             }
  39.             Console.WriteLine($"{userId}登录成功,ConnectionId={Context.ConnectionId}");
  40.             //向所有用户发送当前在线的用户列表
  41.             Clients.All.SendAsync("Users", dictUsers.Keys.ToList());
  42.         }
  43.         /// <summary>
  44.         /// 退出功能,当客户端退出时调用
  45.         /// </summary>
  46.         /// <param name="userId"></param>
  47.         public void Logout(string userId)
  48.         {
  49.             if (dictUsers.ContainsKey(userId))
  50.             {
  51.                 dictUsers.Remove(userId);
  52.             }
  53.             Console.WriteLine($"{userId}退出成功,ConnectionId={Context.ConnectionId}");
  54.         }
  55.     }
复制代码
实时推送任务定义:
  1. /// <summary>
  2.     /// 定义定时任务
  3.     /// </summary>
  4.     public class MyWorker
  5.     {
  6.         /// <summary>
  7.         /// 单例
  8.         /// </summary>
  9.         public static MyWorker Instance;
  10.         /// <summary>
  11.         /// 锁
  12.         /// </summary>
  13.         private static readonly object locker = new object();
  14.         /// <summary>
  15.         /// 集线器请求上下文
  16.         /// </summary>
  17.         private IHubContext<MyHub> context;
  18.         /// <summary>
  19.         /// 定时器
  20.         /// </summary>
  21.         public static System.Timers.Timer timer;
  22.         /// <summary>
  23.         /// 构造注入
  24.         /// </summary>
  25.         /// <param name="context"></param>
  26.         public MyWorker(IHubContext<MyHub> context)
  27.         {
  28.             this.context = context;
  29.             timer = new System.Timers.Timer(1000);//单位毫秒
  30.             timer.Enabled = true;
  31.             timer.AutoReset = true;//自动重新
  32.             timer.Elapsed += Timer_Elapsed;
  33.             timer.Start();
  34.         }
  35.         /// <summary>
  36.         /// 时钟到达事件
  37.         /// </summary>
  38.         /// <param name="sender"></param>
  39.         /// <param name="e"></param>
  40.         private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
  41.         {
  42.             //模拟数据,一般情况下,从数据库获取,然后通知到客户端
  43.             Dictionary<string, object> data = new Dictionary<string, object>();
  44.             var online = new Random().Next(0, 100);
  45.             var male = Math.Floor(new Random().NextSingle() * online);
  46.             var female = online - male;
  47.             data["online"] = online;
  48.             data["male"] = male;
  49.             data["female"] = female;
  50.             context.Clients.All.SendAsync("Data", data);
  51.         }
  52.         /// <summary>
  53.         /// 单例注册服务
  54.         /// </summary>
  55.         /// <param name="context"></param>
  56.         public static void Register(IHubContext<MyHub> context)
  57.         {
  58.             if (Instance == null)
  59.             {
  60.                 lock (locker)
  61.                 {
  62.                     if (Instance == null)
  63.                     {
  64.                         Instance = new MyWorker(context);
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.     }
复制代码
全局注册SignaIR服务:
  1. using Microsoft.AspNetCore.SignalR;
  2. using SignalRApi.Hubs;
  3. using SignalRApi.Jobs;
  4. var builder = WebApplication.CreateBuilder(args);
  5. // Add services to the container.
  6. builder.Services.AddControllers();
  7. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
  8. builder.Services.AddEndpointsApiExplorer();
  9. builder.Services.AddSwaggerGen();
  10. //1.添加注册SignalR服务
  11. builder.Services.AddSignalR();
  12. var app = builder.Build();
  13. // Configure the HTTP request pipeline.
  14. if (app.Environment.IsDevelopment())
  15. {
  16.     app.UseSwagger();
  17.     app.UseSwaggerUI();
  18. }
  19. //使用路由
  20. app.UseRouting();
  21. app.UseHttpsRedirection();
  22. app.UseAuthorization();
  23. //在Use中注册单例实例
  24. app.Use(async (context, next) =>
  25. {
  26.     var hubContext = context.RequestServices
  27.                             .GetRequiredService<IHubContext<MyHub>>();
  28.     MyWorker.Register(hubContext);//调用静态方法注册
  29.     if (next != null)
  30.     {
  31.         await next.Invoke();
  32.     }
  33. });
  34. app.MapControllers();
  35. //2.映射路由
  36. app.UseEndpoints(endpoints => {
  37.     endpoints.MapHub<MyHub>("/myhub");//启用SignalR中间件,并且设置当客户端通过SignalR请求“/myhub”这个路径的时候,由ChatHub进行处理。
  38. });
  39. app.Run();
复制代码
四、建立SignalR客户端:

客户端界面设计:


客户端依赖:

客户端下载安装Nuget包:Microsoft.AspNetCore.SignalR.Client
  1. dotnet add package Microsoft.AspNetCore.SignalR.Client --version 6.0.8
复制代码
客户端代码—点击事件定义:
  1.         #region 点击事件
  2.         /// <summary>
  3.         /// 建立连接
  4.         /// </summary>
  5.         /// <param name="sender"></param>
  6.         /// <param name="e"></param>
  7.         private void btConnect_Click(object sender, EventArgs e)
  8.         {
  9.             //1.初始化
  10.             InitInfo();
  11.             //2.监听
  12.             Listen();
  13.             //3.连接
  14.             Link();
  15.             //4.登录
  16.             Login();
  17.         }
  18.         /// <summary>
  19.         ///断开连接
  20.         /// </summary>
  21.         /// <param name="sender"></param>
  22.         /// <param name="e"></param>
  23.         private void btDistinct_Click(object sender, EventArgs e)
  24.         {
  25.             hubConnection.InvokeAsync("Logout", "12345");
  26.             _isDistinct = true;
  27.         }
  28.         #endregion
复制代码
客户端代码—SignaIR连接与监听定义:
  1.         #region 连接和监听
  2.         /// <summary>
  3.         /// 是否断开连接
  4.         /// </summary>
  5.         private bool _isDistinct = false;
  6.         /// <summary>
  7.         /// 集线器连接对象
  8.         /// </summary>
  9.         private HubConnection hubConnection;
  10.         /// <summary>
  11.         /// 初始化Connection对象
  12.         /// </summary>
  13.         private void InitInfo()
  14.         {
  15.          hubConnection = new HubConnectionBuilder().WithUrl("http://localhost:5275/myhub").WithAutomaticReconnect().Build();//必须和在服务器端MapHub注册单例实例设置的路径一致;
  16.             hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(5);
  17.         }
  18.         /// <summary>
  19.         /// 监听
  20.         /// </summary>
  21.         private void Listen()
  22.         {
  23.             hubConnection.On<Dictionary<string, object>>("Data", ReceiveInfos);
  24.         }
  25.         /// <summary>
  26.         /// 连接
  27.         /// </summary>
  28.         private async void Link()
  29.         {
  30.             try
  31.             {
  32.                 await hubConnection.StartAsync();//建立完成一个客户端到集线器的连接。
  33.             }
  34.             catch (Exception ex)
  35.             {
  36.                 MessageBox.Show(ex.Message);
  37.             }
  38.         }
  39.         /// <summary>
  40.         /// /监听事件
  41.         /// </summary>
  42.         /// <param name="data"></param>
  43.         private void ReceiveInfos(Dictionary<string, object> data)
  44.         {
  45.             if (data == null || data.Count < 1 || _isDistinct)
  46.             {
  47.                 return;
  48.             }
  49.             this.tbOnline.Text = data["online"]?.ToString();
  50.             this.tbMale.Text = data["male"]?.ToString();
  51.             this.tbFemale.Text = data["female"]?.ToString();
  52.         }
  53.        /// <summary>
  54.        /// 登录
  55.        /// </summary>
  56.         private void Login()
  57.         {
  58.             hubConnection.InvokeAsync("Login", "12345");
  59.             _isDistinct =false;
  60.         }
  61.         #endregion
复制代码
五、运行演示:

启动服务:


启动客户端:


接收实时数据推送:


服务端控制台打印输出:


源码链接地址:

Gitee完整项目实例地址:

https://gitee.com/mingliang_it/SignalRDemo

来源:https://www.cnblogs.com/wml-it/archive/2023/08/25/17656056.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具