ASP.NET Core实时库SignalR简单应用
|
一、什么是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服务端:
项目架构:
集线器服务定义:
- /// <summary>
- /// 定义集线器
- /// </summary>
- public class MyHub : Hub
- {
- /// <summary>
- /// 用户字典
- /// </summary>
- private static Dictionary<string, string> dictUsers = new Dictionary<string, string>();
- /// <summary>
- /// 建立连接回调
- /// </summary>
- /// <returns></returns>
- public override Task OnConnectedAsync()
- {
- Console.WriteLine($"ID:{Context.ConnectionId} 已连接");
- return base.OnConnectedAsync();
- }
- /// <summary>
- /// 断开连接回调
- /// </summary>
- /// <param name="exception"></param>
- /// <returns></returns>
- public override Task OnDisconnectedAsync(Exception? exception)
- {
- Console.WriteLine($"ID:{Context.ConnectionId} 已断开");
- return base.OnDisconnectedAsync(exception);
- }
- /// <summary>
- /// 登录功能,将用户ID和ConntectionId关联起来
- /// </summary>
- /// <param name="userId"></param>
- public void Login(string userId)
- {
- if (!dictUsers.ContainsKey(userId))
- {
- dictUsers[userId] = Context.ConnectionId;
- }
- Console.WriteLine($"{userId}登录成功,ConnectionId={Context.ConnectionId}");
- //向所有用户发送当前在线的用户列表
- Clients.All.SendAsync("Users", dictUsers.Keys.ToList());
- }
- /// <summary>
- /// 退出功能,当客户端退出时调用
- /// </summary>
- /// <param name="userId"></param>
- public void Logout(string userId)
- {
- if (dictUsers.ContainsKey(userId))
- {
- dictUsers.Remove(userId);
- }
- Console.WriteLine($"{userId}退出成功,ConnectionId={Context.ConnectionId}");
- }
- }
复制代码 实时推送任务定义:
- /// <summary>
- /// 定义定时任务
- /// </summary>
- public class MyWorker
- {
- /// <summary>
- /// 单例
- /// </summary>
- public static MyWorker Instance;
- /// <summary>
- /// 锁
- /// </summary>
- private static readonly object locker = new object();
- /// <summary>
- /// 集线器请求上下文
- /// </summary>
- private IHubContext<MyHub> context;
- /// <summary>
- /// 定时器
- /// </summary>
- public static System.Timers.Timer timer;
- /// <summary>
- /// 构造注入
- /// </summary>
- /// <param name="context"></param>
- public MyWorker(IHubContext<MyHub> context)
- {
- this.context = context;
- timer = new System.Timers.Timer(1000);//单位毫秒
- timer.Enabled = true;
- timer.AutoReset = true;//自动重新
- timer.Elapsed += Timer_Elapsed;
- timer.Start();
- }
- /// <summary>
- /// 时钟到达事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
- {
- //模拟数据,一般情况下,从数据库获取,然后通知到客户端
- Dictionary<string, object> data = new Dictionary<string, object>();
- var online = new Random().Next(0, 100);
- var male = Math.Floor(new Random().NextSingle() * online);
- var female = online - male;
- data["online"] = online;
- data["male"] = male;
- data["female"] = female;
- context.Clients.All.SendAsync("Data", data);
- }
- /// <summary>
- /// 单例注册服务
- /// </summary>
- /// <param name="context"></param>
- public static void Register(IHubContext<MyHub> context)
- {
- if (Instance == null)
- {
- lock (locker)
- {
- if (Instance == null)
- {
- Instance = new MyWorker(context);
- }
- }
- }
- }
- }
复制代码 全局注册SignaIR服务:
- using Microsoft.AspNetCore.SignalR;
- using SignalRApi.Hubs;
- using SignalRApi.Jobs;
- var builder = WebApplication.CreateBuilder(args);
- // Add services to the container.
- builder.Services.AddControllers();
- // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
- builder.Services.AddEndpointsApiExplorer();
- builder.Services.AddSwaggerGen();
- //1.添加注册SignalR服务
- builder.Services.AddSignalR();
- var app = builder.Build();
- // Configure the HTTP request pipeline.
- if (app.Environment.IsDevelopment())
- {
- app.UseSwagger();
- app.UseSwaggerUI();
- }
- //使用路由
- app.UseRouting();
- app.UseHttpsRedirection();
- app.UseAuthorization();
- //在Use中注册单例实例
- app.Use(async (context, next) =>
- {
- var hubContext = context.RequestServices
- .GetRequiredService<IHubContext<MyHub>>();
- MyWorker.Register(hubContext);//调用静态方法注册
- if (next != null)
- {
- await next.Invoke();
- }
- });
- app.MapControllers();
- //2.映射路由
- app.UseEndpoints(endpoints => {
- endpoints.MapHub<MyHub>("/myhub");//启用SignalR中间件,并且设置当客户端通过SignalR请求“/myhub”这个路径的时候,由ChatHub进行处理。
- });
- app.Run();
复制代码 四、建立SignalR客户端:
客户端界面设计:
客户端依赖:
客户端下载安装Nuget包:Microsoft.AspNetCore.SignalR.Client- dotnet add package Microsoft.AspNetCore.SignalR.Client --version 6.0.8
复制代码 客户端代码—点击事件定义:
- #region 点击事件
- /// <summary>
- /// 建立连接
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btConnect_Click(object sender, EventArgs e)
- {
- //1.初始化
- InitInfo();
- //2.监听
- Listen();
- //3.连接
- Link();
- //4.登录
- Login();
- }
- /// <summary>
- ///断开连接
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btDistinct_Click(object sender, EventArgs e)
- {
- hubConnection.InvokeAsync("Logout", "12345");
- _isDistinct = true;
- }
- #endregion
复制代码 客户端代码—SignaIR连接与监听定义:
- #region 连接和监听
- /// <summary>
- /// 是否断开连接
- /// </summary>
- private bool _isDistinct = false;
- /// <summary>
- /// 集线器连接对象
- /// </summary>
- private HubConnection hubConnection;
- /// <summary>
- /// 初始化Connection对象
- /// </summary>
- private void InitInfo()
- {
- hubConnection = new HubConnectionBuilder().WithUrl("http://localhost:5275/myhub").WithAutomaticReconnect().Build();//必须和在服务器端MapHub注册单例实例设置的路径一致;
- hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(5);
- }
- /// <summary>
- /// 监听
- /// </summary>
- private void Listen()
- {
- hubConnection.On<Dictionary<string, object>>("Data", ReceiveInfos);
- }
- /// <summary>
- /// 连接
- /// </summary>
- private async void Link()
- {
- try
- {
- await hubConnection.StartAsync();//建立完成一个客户端到集线器的连接。
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message);
- }
- }
- /// <summary>
- /// /监听事件
- /// </summary>
- /// <param name="data"></param>
- private void ReceiveInfos(Dictionary<string, object> data)
- {
- if (data == null || data.Count < 1 || _isDistinct)
- {
- return;
- }
- this.tbOnline.Text = data["online"]?.ToString();
- this.tbMale.Text = data["male"]?.ToString();
- this.tbFemale.Text = data["female"]?.ToString();
- }
- /// <summary>
- /// 登录
- /// </summary>
- private void Login()
- {
- hubConnection.InvokeAsync("Login", "12345");
- _isDistinct =false;
- }
- #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
|
|
|
发表于 2023-8-25 10:07:41
举报
回复
分享
|
|
|
|