在后台主机中托管SignalR服务并广播心跳包

什么是后台主机

在之前的 Asp.NETCore 轻松学系列中,曾经介绍过一个轻量级服务主机 IHostedService ,利用 IHostedService 可以轻松的实现一个系统级别的后台服务,该服务跟随系统启动和停止;同时,其使用异步加载和兼容注入的特性,可以很好的实现业务的扩展和隔离。

IHostedService 有一个默认的实现基类 Microsoft.Extensions.Hosting.BackgroundService,我们仅需要继承 BackgroundService 即可实现后台主机。

本文主要目的在于实现一个后台心跳广播包,所有连接到 SignalR 的客户端,通过订阅心跳包广播频道,能够自动收到服务器发送的心跳广播

广播协议定义

    public interface IHeartbeat
    {
        Task HeartbeatAsync(int data);
    }

上面定义 了一个接口 IHeartbeat,该接口有一个异步的方法 HeartbeatAsync,主要就是心跳的定义,先不管它怎么使用,我们继续往下

定义一个泛型的 Hub

    public class WeChatHub : Hub<IHeartbeat>
    {
        public void Send(ChatMessage body)
        {
            Clients.All.RecvAsync(body);
        }

        public override Task OnConnectedAsync()
        {
            Console.WriteLine("游客[{0}]进入了聊天室", this.Context.ConnectionId);
            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            Console.WriteLine("游客[{0}]离开了聊天室", this.Context.ConnectionId);
            return base.OnDisconnectedAsync(exception);
        }
    }

上面定义了一个SignalR通信管理对象 WeChatHub ,其继承字泛型的 Hub,其中,泛型类型指定为 IHeartbeat 接口,这里的泛型即表示 SignalR 的客户端,其代表一种通信协议包,SignalR 的客户端(各种类型的)如果希望收到 IHeartbeat 定义的消息(方法实现),必须侦听 IHeartbeat 的定义(方法名称和参数)

上面的这段话比较绕口,其实我也觉得不太好理解,简单来说就是客户端要侦听一个和 SignalR 服务端定义的相同的频道,才可以收到广播。

定义后台服务主机

在定义好 SignalR 的通信协议后,接下来要做的就是实现一个后台服务主机,也就是 IHostedService 的实现。根据 Asp.Net Core 轻松学-基于微服务的后台任务调度管理器 中的提示,我们不需要实现这个接口,只需要继承 Microsoft.Extensions.Hosting.BackgroundService 即可

实现代码
    public class WeChatHubWorker : BackgroundService
    {
        private readonly IHubContext<WeChatHub, IHeartbeat> heartbeat;
        public WeChatHubWorker(IHubContext<WeChatHub, IHeartbeat> heartbeat)
        {
            this.heartbeat = heartbeat;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                await this.heartbeat.Clients.All.HeartbeatAsync(0);
                await Task.Delay(3000);
                Console.WriteLine("heartbeat");
            }
        }
    }

上面的代码比较简单,首先定义了 IHubContext<WeChatHub, IHeartbeat> 对象 heartbeat,然后在构造函数中通过注入的方式将其实例化,紧接着在 ExecuteAsync(CancellationToken stoppingToken) 方法中,执行了一个无限循环的操作,每 3000 毫秒给所有 SignalR 客户端发送一个内容为 0 的心跳包。

服务注入

实现了后台主机后,需要将其注入到 Asp.NETCore 的管道中

// 添加服务主机随主机启动
public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
        services.AddHostedService<WeChatHubWorker>();
         ...
    }

// 配置 SignalR 侦听的 Uri 地址
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseSignalR(routes =>
        {
            routes.MapHub<WeChatHub>("/wechatHub");
        });
        ...
    }

通过服务注入,我们就完成了服务端的实现,下面看看 JavaScript 的实现。

JavaScript 客户端的实现

var connection = new signalR.HubConnectionBuilder()
    .withUrl("/wechatHub")
    .build();

connection.on("RecvAsync", function (data) {
    var li = document.createElement("li");
    li = $(li).text(data.userName + ":" + data.content);
    $("#msgList").append(li);
});

connection.on("HeartbeatAsync", (data) => {
    console.log(data);
});

connection.start()
    .then(function () {
        console.log("客户端已连接");
    }).catch(function (err) {
        console.log(err);
    });

上面的代码,如果有看过前两章的同学,应该是非常熟悉的,这里就不多解释了;但是,由于本次 SignalR 服务端的 Hub 实现不太一样,所以,这里还是要解释一下。

上面的代码分别侦听了两个通道 connection.on("RecvAsync",...) 和 connection.on("HeartbeatAsync",...) ,这两个通道对应服务端的 IHeartbeat 的定义的成员名称,然后在 Callback 中的参数,也需要和 IHeartbeat 定义的一样,保证可以完整接收服务端推送的消息。

  • RecvAsync 通道用来接收和发送客户端的聊天消息(主动/被动)
  • HeartbeatAsync 通道用来接收来自服务端推送的心跳广播(被动)

运行演示

运行服务端,分别打开两个客户端,同时观察服务端和客户端的心跳输出

红圈处就是心跳广播的内容:0。

使用两个客户端分别发送聊天消息

红圈处就是聊天消息。

扩展

如果需要开通多个通道的话怎么办呢,聪明的你一定想到了,就是增加 IHeartbeat 的定义,然后在客户端订阅该频道即可。

示例代码下载

https://github.com/lianggx/Examples/tree/master/SignalR/Ron.SignalRLesson3

原文地址:https://www.cnblogs.com/viter/p/10771974.html

时间: 2024-11-02 15:13:30

在后台主机中托管SignalR服务并广播心跳包的相关文章

郑州互维科技有限公司专业提供域名注册、虚拟主机、云主机、托管租用服务

郑州互维科技有限公司,专业的服务器租用/托管IDC服务商,公司以为客户提供专业.优质.全面的IDC服务为宗旨,倾力打造服务于社会的高效企业.目前我司的机房有境内境外,涉及各个地域:其中有堪比境内双线的韩国KT机房(配有IPMI):高硬防.大带宽.多IP的美国HE和VM机房:80G金盾NP集群.300G电信+100G联通出口的华东地区安全级别最高双线机房之一的宿迁双线机房:无需手工添加白名单即可实现有备案自动允许访问.40G金盾NP集群的镇江电信机房:运用BGP技术实现高数据通畅率.境内不用实行备

创建自托管的SignalR服务端

微软官方例子地址:http://www.asp.net/signalr/overview/deployment/tutorial-signalr-self-host 1.说明: SignalR服务端可以使Asp.net程序,也就可以是控制台或服务程序这种不需要再IIS上托管的程序.这就是本篇文章的内容介绍. 2.安装扩展: 使用Nuget控制台:Install-Package Microsoft.AspNet.SignalR.SelfHost自托管服务端所需要的程序集. Install-Pack

SignalR入门之多平台SignalR服务端

之前创建SignalR服务端是基于Web应用程序而言的.那么能不能把SignalR服务端做成控制台应用程序.Winform或windows服务呢? 答案是肯定的. 之前尽管看起来好像是IIS和ASP.Net构成托管SignalR服务的唯一环境,但事实上并非如此,很多情况下采用的并非是IIS和ASP.NET. 现在,在这里以控制台程序为例,将SignalR服务端建立在控制台程序里. 如何在控制台程序实现基于Hub或持久性连接的SignalR服务呢,首先安装下面的包: install-package

Signalr 实现心跳包

项目分析: 一个实时的IM坐席系统,客户端和坐席使用IM通信,客户端使用android和ios的app,坐席使用web. web端可以保留自己的登录状态,但为防止意外情况的发生(如浏览器异常关闭,断网,断电),对坐席的实时在线状态造成影响,我们在后台跑一个服务,实时向每个坐席发送一个心跳包,当坐席的状态是在线,但是又不能接收到服务端的心跳包的时候,认为该坐席已经被异常下线. 实时通信Signalr 使用中发现signalr的服务端必须需要 .net frameword4.5及以上版本,对sign

IIS 中托管基于TCP绑定的WCF服务

IIS 中托管基于TCP绑定的WCF服务 一.创建一个基于TCP绑定的WCF服务 1.创建一个的简单的服务具体代码如下 服务契约定义 namespace SimpleService { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IHelloService”. [ServiceContract] public interface IHelloService { [OperationContract] string GetMessage(string m

在windows服务中托管asp.net.core

参考:https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-3.1&tabs=visual-studio 背景:项目各个模块部署在不同位置,因此采用了微服务架构.由于安装部署环境的差异,部分模块只能部署在xp系统下,其他部署环境考虑使用net.core,在windows服务中托管webapi,或者在webapi中寄宿windows服务,总而言之就是在一个程序中将wi

CentOS----宿主机无法访问虚拟机中的web服务解决方案

宿主机无法访问虚拟机中的web服务 在Windows7宿主机中的VMware虚拟机中安装了CentOS6.5操作系统,并且基于Nginx搭建了Web服务器,网页刚刚搭建好的时候,通过宿主机的浏览器可以访问虚拟机中的网页.但是过了一会儿,就无法访问了,这个问题困扰了自己好几天,每次只好通过虚拟机快照返回到刚刚建立好web服务的那一步,这样就能访问了,但过了一会儿又不能访问了. 后来通过网上查找资料,终于明白了,是一位CentOS6.5的防火墙没有开通web服务的80端口,屏蔽了外部的访问.有两种方

三十、【C#.Net开发框架】WCFHosting服务主机的利用WCF服务通讯和实现思路

回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://pan.baidu.com/s/1eQCc69G        前言:以前的系统都是直接客户端直连数据库服务器,后来考虑到服务器的安全性.数据库连接数的限制.分布能力差等问题,特别是那几年中间件.SOA.ESB等炒得比较火,为了跟上时代脚本有必要开发一个中间件,把后台逻辑业务在中间件中运行.刚开始考虑过WebS

如何在ubuntu中启用SSH服务

如何在ubuntu14.04 中启用SSH服务 开篇科普:  SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定:SSH 为建立在应用层和传输层基础上的安全协议.SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题.SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台.SSH在正确使用时可弥补网络中的漏洞.SSH客户端适用于多种平台