在後臺主機中托管SignalR服務並廣播心跳包

来源:https://www.cnblogs.com/viter/archive/2019/04/26/10771974.html
-Advertisement-
Play Games

本文主要目的在於實現一個後臺心跳廣播包,所有連接到 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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Python基礎之函數的基本使用,函數的參數與返回值,函數的嵌套調用,模塊的介紹;其中,函數的基本使用包括 函數定義的語法,函數的命名規則,函數的調用,函數的註意事項,函數的文檔註釋等;函數的參數與返回值包括 函數參數的使用,形參和實參,函數返回值;函數的嵌套調用包括 函數嵌套調用示例,給函數增加文... ...
  • 廢話不多說,直接開始 1.首先,導入所需的模塊: 關閉tensorflow輸出的一大堆硬體信息 2.寫一個函數generate_data(),用來生成我們所需要的數據,這裡使用的線性函數是y = 0.1*x + 0.3,具體解釋見註釋 說一下上面8,9兩行的操作,其實 與 等價,只是這樣寫比較方便。 ...
  • SynchronousQueue的實現方式? SynchronousQueue真的是無緩衝的嗎? SynchronousQueue在高併發情景下會有什麼問題? ...
  • final關鍵字可用於修飾類、方法和變數,final修飾的類不能被繼承;final修飾的方法不可被重寫;final修飾的變數不可被改變。 1. final類 final修飾的類不能被繼承意思是final修飾的類不可以有子類,java.lang.Math類就是一個final類,它不可以有子類。 定義一 ...
  • JDBC是由java編程語言編寫的類及介面組成,同時它為程式開發人員提供了一組用於實現對資料庫訪問的JDBC API,並支持SQL語言。利用JDBC可以將JAVA代碼連接到oracle、DB2、SQLServer、MYSQL等資料庫,從而實現對資料庫中的數據操作的目的。 一、JDBC簡介 JDBC全 ...
  • IdentityServer實現以下規範: 3.1 OpenID Connect OpenID Connect Core 1.0 ( "規範" ) OpenID Connect Discovery 1.0 ( "規範" ) OpenID Connect Session Management 1.0 ...
  • 規範、文檔和對象模型等都使用特定的術語來表述。 2.1 IdentityServer IdentityServer是OpenID Connect提供程式 它實現OpenID Connect和OAuth 2.0協議。 對於相同的角色,不同的文獻將使用不同的術語 —— 你可能也發現了安全令牌服務(Sec ...
  • 大多數現代應用程式或多或少看起來像這樣: 最常見的互動是: 瀏覽器與Web應用程式通信 Web應用程式與Web API進行通信(Web應用程式自身 或 代表用戶 與 Web API 通信) 基於瀏覽器的應用程式與Web API通信 本地應用程式與Web API通信 基於伺服器的應用程式與Web AP ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...