SignalR 简介与核心功能

谈一谈Signal R

Signal R 是一个用于 ASP.NET 开发的库,它简化了向应用程序添加实时 Web 功能的过程。实时 Web 功能指的是服务器代码能够在内容可用时立即推送到连接的客户端,而不是等待客户端请求新数据

实时通信:SignalR 允许服务器端代码通过远程过程调用 (RPC) 调用客户端浏览器中的 JavaScript 函数,从而实现实时通信

多种传输方式:SignalR 使用 WebSocket 作为主要传输方式,并在必要时回退到其他传输方式

连接管理:SignalR 自动处理连接管理,并允许广播消息到所有连接的客户端,或发送消息到特定客户端

扩展性:SignalR 应用程序可以扩展到数千个客户端,支持使用 Redis、SQL Server 或 Azure Service Bus 进行消息协调

在线的概念与传统的数据传输不同 他保持在线的时候,你在通讯。

Signal R  仅仅是服务的通讯。以这个服务服务为基础,可以影射到WPF的应用程序,MAUI的应用程序以及web assembly blazor. 各种应用程序通过服务连接起来.

整个过程是依据Microsoft.AspNetCore.SignalR.Client。

通讯过程放在下边这个hub里头,它是一个实体(class)。

很有意思的一点是,hub的定义是在服务端完成的。其他各个应用程序只要使用Microsoft.AspNetCore.SignalR.Client。就可以完成相互之间的通讯。当然,哈勃所承载的实体必须在各个客户端及服务端定义.

 下面用两个实体student和teacher来表明HUB是怎么样承载这些实体并进行传输的

首先我们有两个class  student  teacher   一般来讲,这个被承载的实体的class应该是能够被json系列化的.

namespace BlazorSingal.Hubs

{

  public class Student

  {

    public int StudentId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public DateTime BirthDate { get; set; }

    // Other student-specific properties and methods can be added here.

  }

  public class Teacher

  {

    public int TeacherId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Subject { get; set; }

    // Other teacher-specific properties and methods can be added here.

  }

}

下面定义了一组用于发送这两个实体的方法。这里我们使用的All,假设是一个广播。事实上你有,你有其他的选择。Caller , Other  Group

using Microsoft.AspNetCore.SignalR;

namespace  BlazorSingal.Hubs

{

  public class DataHubs : Hub

  {

    public async Task SendStudentAndTeacher(string user, Student student, Teacher teacher)

    {

      await Clients.All.SendAsync("ReceiveStudentAndTeacher", user, student, teacher);

    }

    public async Task NotifyStudent(string user, Student student)

    {

      await Clients.All.SendAsync("ReceiveStudentNotification", user, student);

    }

    public async Task AlertTeacher(string user, Teacher teacher)

    {

      await Clients.All.SendAsync("ReceiveTeacherAlert", user, teacher);

      await Clients.Caller.SendAsync("ReceiveTeacherAlert", user, teacher);

    }

  }

}

SendStudentAndTeache, NotifyStudenAlertTeacher   是你将使用的发送方法

ReceiveStudentAndTeacher", ReceiveStudentNotification ReceiveTeacherAlert接受的关键字 

User   是接收以后用来再分配的关键字,

下面是发送的举例    反正是C#在哪都行在什么app  ,server..  maui

if (hubConnection is not null)

 {

   await hubConnection.SendAsync("NotifyStudent", "Send by student", student);

 }

async Task Exe_SendTeacher()

{

  M_state("Task SendTeacher ".Replace("_", " ") + " continue working!");

  var cur_time = DateTime.Now;

  await Task.Run(async () =>

  {

    var teacher = new Teacher()

    {

      LastName = t_WPFTacherpp.Split('_')[0] 

    };

    await hubConn.SendAsync("ReceiveTeacherAlert", "Send by techer", teacher);

    M_state("SendTeacher ".Replace("_", " ") +

        DateTime.Now.Subtract(cur_time).TotalMinutes.ToString("F2")

         + " minute ");

  });

}

下面是接收的状态 。也是,在哪都行,反正是c#

hubConnection.On<string, Student,Teacher>("ReceiveStudentAndTeacher", (user, Tstudent,Tteacher) =>

 {

   var encodedMsg = $"{user} :   {student.LastName}  {student.FirstName}  {student.BirthDate}  "+

   $"th:{Tteacher.LastName} {Tteacher.FirstName}    ";

   messages.Add(encodedMsg);

   InvokeAsync(StateHasChanged);

 });

下面是一个prism中的例子我把它放在viewModel里头在

     base.Check_base_timer_Tick(sender, e);

     ((DispatcherTimer)sender).Stop();

     hubConn.On<string, Student, Teacher>("ReceiveStudentAndTeacher", (user, Tstudent, Tteacher) =>

     {

       t_Sender= user;

       t_WPFStudentpp = new WPFStudent(Tstudent);

       t_ReceiveList.Add(user+"-->"+

         Tteacher.LastName + " _ " + Tteacher.FirstName +"_"+ Tteacher.TeacherId);

     });

服务端的connection是通过依赖注册项来完成的

program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddRazorComponents()

    .AddInteractiveServerComponents()

    .AddInteractiveWebAssemblyComponents();

builder.Services.AddCascadingAuthenticationState();

builder.Services.AddScoped<IdentityUserAccessor>();

builder.Services.AddScoped<IdentityRedirectManager>();

builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>();

builder.Services.AddAuthentication(options =>

    {

      options.DefaultScheme = IdentityConstants.ApplicationScheme;

      options.DefaultSignInScheme = IdentityConstants.ExternalScheme;

    })

    .AddIdentityCookies();

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");

builder.Services.AddDbContext<ApplicationDbContext>(options =>

    options.UseSqlite(connectionString));

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)

    .AddEntityFrameworkStores<ApplicationDbContext>()

    .AddSignInManager()

    .AddDefaultTokenProviders();

builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

#region for SignaR  依赖注册项

builder.Services.AddSignalRCore();

builder.Services.AddResponseCompression(opts =>

{

  opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(

      ["application/octet-stream"]);

});

builder.Services.AddCors(options =>

{

  options.AddPolicy("CorsPolicy", builder =>

  {

    builder.WithOrigins("https://example.com")

           .AllowAnyMethod()

           .AllowAnyHeader();

  });

});

#endregion

var app = builder.Build();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{

  app.UseWebAssemblyDebugging();

  app.UseMigrationsEndPoint();

}

else

{

  app.UseExceptionHandler("/Error", createScopeForErrors: true);

  // The default HSTS value is 30 days. You may want to change this for production scenarios, see Enforce HTTPS in ASP.NET Core | Microsoft Learn.

  app.UseHsts();

}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseAntiforgery();

app.MapRazorComponents<App>()

    .AddInteractiveServerRenderMode()

    .AddInteractiveWebAssemblyRenderMode()

    .AddAdditionalAssemblies(typeof(BlazorSingal.Client._Imports).Assembly);

// Add additional endpoints required by the Identity /Account Razor components.

app.MapAdditionalIdentityEndpoints();

app.MapHub<DataHubs>("/DataHubs", options =>

{

  // 在这里配置 HttpConnectionDispatcherOptions

  // 例如,设置最大连接数、跨域策略等

  options.Transports = HttpTransportType.WebSockets | HttpTransportType.LongPolling;

  // 其他配置...

});

app.Run();

其他应用的hub connection的设置是一样的,反正通过c#完成。

      DispatcherTimer check__SignalR_timer = new DispatcherTimer();

      check__SignalR_timer.Tick += new EventHandler(CheckSingalR_timer_Tick);

      check__SignalR_timer.Interval = new TimeSpan(0, 0, 5);

      check__SignalR_timer.Start();

if (hubConn == null)

 {

   hubConn = new HubConnectionBuilder()

    .WithUrl(O_setting.UrlST) // Replace with your actual hub URL

    .WithAutomaticReconnect()

    .Build();

 }

建立连接以后,不管连上没连上  hubConn我经  有了   不是空的。State !=

在下面的循环中不断检查如果没连上告诉用户一声

async private void CheckSingalR_timer_Tick(object sender, EventArgs e)

{

  ((DispatcherTimer)sender).Stop();

  t_ReceiveList.Add("start");

  if(hubConn.State != HubConnectionState.Connected)

  {

    t_Color_StateSingalR = "#33AA0606";

    t_StateSingalR = "Connecting";

    // Create a cancellation token source.

    using var cts = new CancellationTokenSource();

    for (int i = 0; i < 3; i++)

    {

      try

      {

        await hubConn.StartAsync(cts.Token);

        if (hubConn.State == HubConnectionState.Connected) goto Conn_ed;

      }

      catch when (cts.Token.IsCancellationRequested)

      {

        goto  NotConn_ed;

      }

      catch

      {

        // Failed to connect; trying again after a delay.

        await Task.Delay(5000, cts.Token);

      }

    }

  NotConn_ed:;

    ((DispatcherTimer)sender).Start();

    t_Color_StateSingalR = "#66AA0606";

    t_StateSingalR = "Offline. Check your network";

    return;

  Conn_ed:;

      

    t_Color_StateSingalR = "#FFFFFFFF";

    t_StateSingalR = "OnLine";

  }

  else

  {

    if(t_StateSingalR != "OnLine")

    {

      t_Color_StateSingalR = "#FFFFFFFF";

      t_StateSingalR = "OnLine";

    }

  }

          ((DispatcherTimer)sender).Start();

}

如果没连上,告诉用户一声,

可以参考下面的源程序,写的很乱,但意思表达清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值