MQTTnet实现客户端连接

使用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}");
            }

        }
        /// <summary>
        /// 发布消息方法
        /// </summary>
        public static async Task PublishMessage(string host,string topic,string context)             
        {
            // 构建一个新的消息
            var message = new MqttApplicationMessageBuilder()
                .WithTopic(topic)  // 指定主题
                .WithPayload(context)  // 指定发布的内容
                .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtMostOnce)   // 指定消息的服务质量等级(QoS)
                .Build();

            IMqttClient mqttClient = _clients[host];
           await mqttClient.PublishAsync(message, cancellationTokenSource.Token);
        }
    }
}

 连接信息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 Masuit.Tools.Hardware;
using MQTTnet.Diagnostics;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

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


            //获取硬件检测
            //float load = SystemInfo.CpuLoad;//获取CPU占用率
            //var raminfo = RamInfo.Local;//获取内存信息
            //double freePhysicalMemory = SystemInfo.GetFreePhysicalMemory();// 获取可用物理内存
            //Console.WriteLine($"CPU占用率:{load},内存信息:{raminfo},可用物理内存:{freePhysicalMemory}");
            Console.ReadKey();
        }

        private static async Task  MqttTest()
        {
           
            //MqttClientManage clientManager = new MqttClientManage(brokerUris);
            //MqttClientConnect mqttClient = new MqttClientConnect(brokerUris);

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


            ///实现消息发布,模拟每秒发布一次,共2台服务器
            _timer = new Timer(TimerCallback, null, 0, 1000); // 初始延迟0毫秒,然后每1000毫秒(1秒)调用一次  
            //_timer.Change(Timeout.Infinite, 0); // 停止计时器  
            //_timer.Dispose(); // 释放资源  

           
        }
        private static async void TimerCallback(Object state)
        {
            
            foreach (var item in brokerUris)
            {
                if (item =="broker.emqx.io")
                //{
                //    model.puller = "B01";
                //    model.state = 1;
                //    model.crystalid = Guid.NewGuid().ToString().Substring(0, 10);
                //    model.crystalcode =item.ToString();
                //    MqttClientManage.PublishMessage(item, "GF01", JsonConvert.SerializeObject(model));
                //}
                else if (item =="127.0.0.1")
                {
                    model.puller = "C01";
                    model.state = 1;
                    model.crystalid = Guid.NewGuid().ToString().Substring(0, 10);
                    model.crystalcode =item.ToString();
                    MqttClientManage.PublishMessage(item, "GF01", JsonConvert.SerializeObject(model));
                }
            }
        }

    }
}

 在测试过程中,若发布频率很高,但是服务转发频率低,会导致发布客户端内存不断增长,CPU增长,需要对发布客户端进行异常处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值