首页 > 编程语言 >ASP.NET Core实时库SignalR简单应用

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

时间:2023-08-25 09:45:06浏览次数:49  
标签:Core ASP void private SignalR data app 客户端

一、什么是SignalR:

SignalR 是用于构建需要实时用户交互或实时数据更新的Web 应用程序的一个开放源代码.NET 库。不仅仅用在Web应用中,后面会讲到它的应用范围。它简化了简化了构建实时应用程序的过程,包括ASP.NET Server库和JavaScript Client库,以便管理Client与Server连接并将内容更新推送给Client。

SignalR可用于需要实时刷新获取后台数据的程序。常用的场景范围有:社交应用程序、 多用户游戏、 业务协作和新闻,天气或财务更新应用程序等等。
image

二、关于WebSocket知识拓展:

在传统的HTTP中,只能客户端主动向服务器端发起请求,服务器端无法主动向客户端发送消息。有的业务场景下,我们需要服务器端主动向客户端发送消息,比如Web聊天室、OA系统、站内消息等。

为了实现服务器端向客户端推送消息,在2008年诞生了WebSocket协议,并且该协议在2011年成为国际标准。目前所有的主流浏览器都已经支持WebSocket协议。WebSocket基于TCP(transmission control protocol,传输控制协议),支持二进制通信,因此通信效率非常高,它可以让服务器处理大量的并发WebSocket连接;WebSocket是双工通信,因此服务器可以高效地向客户端推送消息。

三、建立SignalR服务端:

项目架构:

image

集线器服务定义:

  /// <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

五、运行演示:

启动服务:

image

启动客户端:

image

接收实时数据推送:

image

服务端控制台打印输出:

image

源码链接地址:

Gitee完整项目实例地址:

https://gitee.com/mingliang_it/SignalRDemo

标签:Core,ASP,void,private,SignalR,data,app,客户端
From: https://www.cnblogs.com/wml-it/p/17656056.html

相关文章

  • 盘点10个.NetCore实用的开源框架项目
    连续分享.Net开源项目快3个月了,今天我们一起梳理下10个,比较受到大家欢迎的.NetCore开源框架项目。更多开源项目,可以查看我创建的,.Net开源项目榜单!一个专注收集.Net开源项目的榜单​github.com/bianchenglequ/netcodetop1、FytSoaCms前后端分离CMS系统项目简介这是一个基于.N......
  • Microsoft.AspNetCore.Identity
    前言用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊。好在asp.netcore给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不是非常个性化的话,identity是一个不错的选择。ASP.NETCoreIdentity:是一个API,它支持用......
  • Basic Authentication in ASP.NET Web API
    BasicAuthenticationinASP.NETWebAPI原始资料:BasicAuthenticationinASP.NETWebAPI|MicrosoftLearn演示了如何实现basic身份验证。 注意:在WebAPI2中,您应该考虑编写身份验证过滤器或OWIN中间件,而不是HTTP模块。InWebAPI2,youshouldconsiderwrit......
  • net6 使用ef core 映射mysql数据库(方法一)
    1.安装下载nuget包Pomelo.EntityFrameworkCore.MySql和Microsoft.EntityFrameworkCore.Design如下图 2.创建一个模型类,之后映射到数据库里面的表、字段和这个类是一致的。publicclassMovies{///<summary>///id///</summary>......
  • .Net Core使用miniExcel实现导入导出
    .NetCore使用miniExcel实现导入导出首先,引入NuGet包:MiniExcel第三方插件一、导入    publicintUpLoadExecl()   {      //获取文件数据,[0]代表只能上传一个文件,如果要传递多个文件注意:文件名不能重复      varformInfor=HttpCo......
  • org.apache.jasper.servlet.TldScanner$TldScannerCallback.scan(Lorg/apache/tomcat/
    原因<dependency><groupId>org.apache.hive</groupId><artifactId>hive-jdbc</artifactId><version>3.1.3</version></dependency>解决<dependency>......
  • Asp.net mvc 笔记
    捕捉处理全局异常自定义一个Attribute继承默认的HandleErrorAttributenamespaceEmpowerApiService.Filter{publicclassCustomerErrorAttribute:HandleErrorAttribute{privatestaticNLog.Loggerlogger=NLog.LogManager.GetCurrentClassLogger();......
  • 【HMS Core】在线语种检测返回结果错误
    ​ 【关键字】在线语种检测、机器学习 【问题描述】集成在线语种检测服务,检测蒙古文之后,返回结果为中文​ 【问题分析】1、在线语种服务目前不支持蒙古文,具体可见官网语种支持列表:【MLKit】语种检测支持的语言列表​2、目前该服务是在支持语言进行置信度识别的,没有......
  • dockerfile netcore 示例
    #syntax=docker/dockerfile:1FROMmcr.microsoft.com/dotnet/sdk:7.0asbuild-envWORKDIR/appCOPY..RUNdotnetrestoreRUNdotnetpublish-cRelease-o/publishFROMmcr.microsoft.com/dotnet/aspnet:7.0asruntimeWORKDIR/srcCOPY--from=build......
  • SignalR实战:在.NET Framework和.NET Core中如何使用SignalR?
    官网文档:ASP.NETCoreSignalR入门|MicrosoftLearnSignalR开源代码:SignalR·GitHub很多小伙伴问:在前后端分离项目中,后端是.NETCore前端是Vue如何使用SignalR?在前后端不分离项目中,.NETFrameworkMVC项目中又如何使用SignalR技术呢?那就来看看下面这篇文章吧!本文主要介绍Signa......