MQTTnet实现客户端连接

news2025/1/10 20:49:58

使用MQTTnet(Version=4.3.1.873)库实现多客户端连接多服务端,同时实现断线重连;

如下图所示,开启3个客户端连接3个服务端,当其一个服务端出现异常(服务停止,网络异常无法连接)导致连接断开时,实现每5秒连接一次

MQTT连接服务核心类:业务需求是一个客户端对应的一个MQTT服务,因此按照服务端个数创建对应的客户端连接,实现通过每一个服务端订阅消息,获取数据

using MQTTnet.Client;
using MQTTnet.Diagnostics;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MqttConnectManage
{
    public class MqttClientManage
    {

        public readonly List<IMqttClient> _clients = new List<IMqttClient>();
        public readonly string[] _serverAdr;
        private List<MqttClientOptions> serverOptions = new List<MqttClientOptions>();
        private readonly IMqttNetLogger logger;
        private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

        /// <summary>
        /// 日志记录
        /// </summary>
        /// <param name="logger"></param>
        public MqttClientManage(IMqttNetLogger logger)
        {
            this.logger = logger;
        }
        /// <summary>
        /// 客户端连接信息
        /// </summary>
        /// <param name="brokerAddress"></param>
        /// <param name="port"></param>
        /// <param name="clientId"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public void AddServer(MQTTServerModel model)
        {
            var options = new MqttClientOptionsBuilder()
                .WithClientId(model.clientId)
                .WithTcpServer(model.brokerAddress, model.port)
                .WithCleanSession()
                .WithCredentials(model.username, model.password)
                .Build();

            serverOptions.Add(options);
        }
        public async Task ConnectAllAsync()
        {
            var mqttFactory = new MqttFactory();
            foreach (var options in serverOptions)
            {
                var mqttClient = mqttFactory.CreateMqttClient();
                //3.连接成功事件
                //mqttClient.ConnectedAsync +=Client_ConnectHandler;
                mqttClient.ConnectedAsync +=(async e =>
                {
                    Console.WriteLine($"【{options.ClientId}】{DateTime.Now.ToShortDateString()}The MQTT client is connected!【{e.ConnectResult.ResultCode}】");
                });


                //4.订阅消息回调事件
                //mqttClient.ApplicationMessageReceivedAsync+=Client_MessageReceivedHandler;
                mqttClient.ApplicationMessageReceivedAsync+=(async e =>
                {
                    Console.WriteLine($"【{DateTime.Now.ToShortDateString()}】[{e.ClientId}]--[{e.ApplicationMessage.Topic}]--Message Payload: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
                });

                //5.断开连接事件
                //mqttClient.DisconnectedAsync +=Client_DisconnectedHandler;
                mqttClient.DisconnectedAsync +=(async e =>
                {
                    Console.WriteLine($"【{options.ClientId}】-{DateTime.Now.ToShortDateString()}-连接断开:{e.Reason}-->{(e.Exception==null ? null : e.Exception.Message)}");
                    Console.WriteLine($"当前客户端数量:{_clients.Count},存活{_clients.Where(n => n.IsConnected == true).ToArray().Length}");
                    await Task.Delay(TimeSpan.FromSeconds(5));//延迟5s重连

                    try
                    {
                        await mqttClient.ConnectAsync(options, cancellationTokenSource.Token);
                        // 2、创建订阅
                        // 2.1创建订阅选项
                        var subscribeOptions1 = new MqttClientSubscribeOptionsBuilder()
                            .WithTopicFilter(f =>
                            {
                                f.WithTopic("GF01")
                                 .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce);
                            })
                            .Build();

                        // 2.2订阅主题
                        var subscribeResult1 = await mqttClient.SubscribeAsync(subscribeOptions1, cancellationTokenSource.Token);
                        // 2.3输出订阅结果
                        foreach (var result in subscribeResult1.Items)
                        {

                            Console.WriteLine($"【订阅主题信息{options.ClientId}】--Subscription Result: Topic = {result.TopicFilter.Topic}, ResultCode = {result.ResultCode}");
                        }
                        //初始未连接将重新加入客户端数组中
                        if (mqttClient.IsConnected &&  !_clients.Contains(mqttClient))
                        {
                            _clients.Add(mqttClient);
                        }
                    }
                    catch
                    {
                        Console.WriteLine("重连失败!!");
                    }
                    Console.WriteLine($"{DateTime.Now.ToShortDateString()} 当前客户端数量:{_clients.Count},存活{_clients.Where(n => n.IsConnected == true).ToArray().Length}");

                });

                // 1.连接服务
                await mqttClient.ConnectAsync(options, cancellationTokenSource.Token);
                // 2、创建订阅
                // 2.1创建订阅选项
                var subscribeOptions = new MqttClientSubscribeOptionsBuilder()
                    .WithTopicFilter(f =>
                    {
                        f.WithTopic("GF01")
                         .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce);
                    })
                    .Build();

                // 2.2订阅主题
                var subscribeResult = await mqttClient.SubscribeAsync(subscribeOptions, cancellationTokenSource.Token);
                // 2.3输出订阅结果
                foreach (var result in subscribeResult.Items)
                {

                    Console.WriteLine($"【订阅主题信息{options.ClientId}】--Subscription Result: Topic = {result.TopicFilter.Topic}, ResultCode = {result.ResultCode}");
                }

                _clients.Add(mqttClient);
                Console.WriteLine($"{DateTime.Now.ToShortDateString()} 当前客户端数量:{_clients.Count},存活{_clients.Where(n => n.IsConnected == true).ToArray().Length}");
            }

        }
    }
}

 连接信息model类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MqttConnectManage
{
    public class MQTTServerModel
    {
        /// <summary>
        /// 服务地址
        /// </summary>
        public string brokerAddress { get; set; }
        /// <summary>
        /// 端口号
        /// </summary>
        public int port { get; set; }
        /// <summary>
        /// 客户端ID
        /// </summary>
        public string clientId { get; set; }
        /// <summary>
        /// 登录用户名
        /// </summary>
        public string username { get; set; }
        /// <summary>
        /// 登录密码
        /// </summary>
        public string password { get; set; }
    }
}

 方法调用

using MQTTnet.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MqttConnectManage
{
    /// <summary>
    /// 使用MQTTnet 4.3.1.873实现多客户端连接多个服务,并且实现异常断开重连
    /// </summary>
    internal class Program
    {
        static void Main(string[] args)
        {
            string[] brokerUris = { "broker.emqx.io", "broker.hivemq.com", "127.0.0.1" };
            //MqttClientManage clientManager = new MqttClientManage(brokerUris);
            //MqttClientConnect mqttClient = new MqttClientConnect(brokerUris);

            IMqttNetLogger logger = null;
            MqttClientManage mqttClient = new MqttClientManage(logger);
            foreach (var item in brokerUris)
            {
                mqttClient.AddServer(new MQTTServerModel() { brokerAddress =item, clientId =item, port =1883, username =null, password=null });
            }
            mqttClient.ConnectAllAsync();

            Console.ReadKey();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1535455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

政安晨:【深度学习实践】【使用 TensorFlow 和 Keras 为结构化数据构建和训练神经网络】(四)—— 过拟合和欠拟合

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 通过增加容量或提前停止来提高性能。 在深度学习中&#…

oracle 19c单机版本补丁升级

文章目录 一、补丁包概述二、备份opatch三、替换高版本opatch四、打DB补丁1、关闭数据库2、关闭监听3、解压补丁4、冲突检测5、补丁空间检查6、执行补丁升级7、将更新内容加载到数据库8、最后查看数据库版本9、卸载补丁包 一、补丁包概述 补丁升级包 链接&#xff1a;https://…

Vue3的与2的简单区别

Vue2选项式api Vue3组合式API setup方法的使用&#xff0c;最后需要return setup语法糖省略了内部的export default{} 和return 内容 以及组件的注册 reactive生成响应式对象&#xff0c;只能适用于复杂对象&#xff0c;简单类型不可 ref生成响应式数据&#xff1a;复杂类型和简…

学习人工智能:Attention Is All You Need-1-介绍;Transformer模型架构

Transformer模型是目前最成功的chatGPT&#xff0c;Sora&#xff0c;文心一言&#xff0c;LLama&#xff0c;Grok的基础模型。 《Attention Is All You Need》是一篇由Google DeepMind团队在2017年发表的论文&#xff0c;该论文提出了一种新的神经网络模型&#xff0c;即Trans…

十七 超级数据查看器 讲解稿 条目内容

十七 超级数据查看器 讲解稿 条目内容 ​​点击此处 以新页面 打开B站 播放当前教学视频 点击访问app下载页面 百度手机助手 下载地址 大家好&#xff0c;今天我们讲解超级数据查看器条目内容设置 条目内容设置能够 设置条目的顺序 显示隐藏 标题 需要下载本系统的…

OpenLayers基础教程——使用WebGL加载海量数据(1)

1、前言 最近遇到一个问题&#xff1a;如何在OpenLayers中高效加载海量的场强点&#xff1f;由于项目中的一些要求&#xff0c;不能使用聚合的方法加载。一番搜索之后发现&#xff1a;OpenLayers中有一个WebGLPoints类&#xff0c;使用该类可以轻松应对几十万的数据量&#xf…

SAP Business Application Studio(BAS)中开发Fiori App的基础知识

1. SAP Fiori Tools SAP Fiori Tools是一套用于支持SAP Fiori应用开发的工具&#xff0c;包括应用模板、可视化编辑器、代码生成、应用预览和集成测试工具等。这些工具可以帮助开发者更快速、更简单地创建和维护SAP Fiori应用。SAP Fiori Tools 可与SAP的开发环境&#xff08;…

Qt 不同数据类型转换

一.不同类型数据转换示例&#xff1a; #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QJsonDocument> #include <QJsonObject> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication::setAttribute…

用OceanBase binlog service 轻松进行数据回滚

背景 在日常的数据库运维过程中&#xff0c;难免会遭遇数据误操作的情形&#xff0c;比如因疏忽而执行了非预期的delete或update操作&#xff0c;这时就需要进行数据回滚。如果在OceanBase中启用了回收站功能&#xff0c;并设置了合适的undo_retention&#xff0c;那么我们可以…

【Frida】10_用鼠标自动标记棋盘上的雷区(一键过关)

&#x1f6eb; 系列文章导航 【Frida】 00_简单介绍和使用 https://blog.csdn.net/kinghzking/article/details/123225580【Frida】 01_食用指南 https://blog.csdn.net/kinghzking/article/details/126849567【Frida】02_常见API示例及功能函数封装&#xff08;snippets&#…

【爬虫】web自动化和接口自动化

专栏文章索引&#xff1a;爬虫 目录 一、介绍 二、推荐 1.接口自动化 2.Web自动化 一、介绍 爬虫技术一般可以分为两种类型&#xff1a;接口自动化和web自动化。下面是它们的简要介绍&#xff1a; 1.接口自动化 接口自动化技术的主要目的是通过模拟HTTP请求来实现自动化…

如何在Linux系统部署Dupal CMS结合内网穿透实现无公网IP访问web界面

文章目录 前言1. Docker安装Drupal2. 本地局域网访问3 . Linux 安装cpolar4. 配置Drupal公网访问地址5. 公网远程访问Drupal6. 固定Drupal 公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&a…

十九、软考-系统架构设计师笔记-真题解析-2021年真题

软考-系统架构设计师-2021年上午选择题真题 考试时间 8:30 ~ 11:00 150分钟 1.前趋图(Precedence Graph)是一个有向无环图&#xff0c;记为&#xff1a;→(Pi,Pj)Pi must Complete Before Pj may strat), 假设系统中进程P{P1, P2,P3,P4, P5, P6, P7, P8}&#xff0c; 且进程的…

软考高级:UML定时图概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

电子证书查询系统如何制作证书?

1、制作空白证书&#xff1a;网上找一张证书背景图&#xff0c;用PPT工具或photoshop等图片处理工具&#xff0c;将证书上固定的文字打上&#xff0c;有公章的话贴上电子公章&#xff0c;不固定的内容留空白。 2、制作电子证书&#xff1a;上传前一步制作好的空白证书&#xf…

浅谈如何自我实现一个消息队列服务器(2)——实现 broker server 服务器

文章目录 一、实现 broker server 服务器1.1 创建一个SpringBoot项目1.2 创建Java类 二、硬盘持久化存储 broker server 里的数据2.1 数据库存储2.1.1 浅谈SQLiteMyBatis 2.1.2 如何使用SQLite 2.2 使用DataBaseManager类封装数据库操作2.3 文件存储消息2.3.1 存储消息时&#…

【leetcode热题】轮转数组

给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4…

react-jsx

react04 jsx语法 - 01 基础知识&#xff1a; jsx javascript xml(html) 把js和heml标签混合到一起 react视图编写及构建的简要流程 &#xff1a; 如何在react中使vs code支持格式化和快捷键提示&#xff1a;1, 2,修改文件后缀为jsx&#xff0c;因为webpack的打包规则中可以…

智能农业:农业技术与效益

文章目录 什么是智慧农业&#xff1f;智能农业的好处智能农业技术物联网智能农业解决方案智能农业软件和移动应用程序智能农业的挑战作物监测卫星智能农业解决方案使用卫星数据数据测量历史数据和预测在便携式设备上使用应用程序 智能农业的未来参考 现代技术的发展影响着人类活…

小车侧方位停车过程的动态模拟matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 小车侧方位停车过程的动态模拟matlab仿真。仿真得到小车的停车动画&#xff0c;小车移动的xy轴坐标以及角度变换。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLA…