C# mqttnet连接mqtt并订阅消费消息的测试代码

文章介绍了如何在VS2022环境下,利用MqttNet库与EMQX5.0MQTT服务器进行交互,通过创建共享订阅来处理多个物联网设备发送的数据。开发了一个MqttNetHelper类用于连接、订阅和接收消息,并展示了Windows桌面程序中接收和存储消息的实现方式。
摘要由CSDN通过智能技术生成

参考:https://blog.csdn.net/yangyong1250/article/details/129403616?spm=1001.2014.3001.5502

IDE环境:vs2022

mqtt服务端:emqx5.0

应用场景:我需要从mqtt建立订阅,对一个topic不停的消费取出下面物联网设备发到mqtt的byte[]消息,然后转存,或者根据通信协议解析消息内容。物联网终端设备可能很多,而免费版的emqx他是不能存储消息的,也不支持对接其他数据库持久化,那么我就要考虑快速的消费所有物联网设备传输过来的消息,可能一个单向订阅不能满足需求。经过查资料,5.0提供了共享订阅机制,可以让多个订阅使用共享订阅的方式从同一个topic主题中取出消息,这种机制目前来看可以满足我的需求。

重点在于订阅的主题前缀是 $share/tahmshare/, 这个前缀后面 跟目标topic就组成了共享订阅。

1、新建一个mqtttest名称的windows桌面程序工程,并从nuget安装mqttnet

2、新建了一个MqttNetHelper类,代码如下, 因为涉及我自己配置的隐私,有些变量清空了,请自行根据注释配置

using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using System.Text;

namespace mqtttest
{
    public class MqttNetHelper
    {
        public IMqttClient mqttClient;
        public bool mqttIsConnected=false;
        public string serverip = "127.0.0.1"; //填写你的服务端IP
        public int serverport = 1883;
        public int KeepAliveSecond = 60;   //心跳间隔
        public string useridstr = ""; //自己在emqx网页管理端新建的账户
        public string passstr = "";  //密码
        
        //消费端我是采用共享订阅$share/tahmshare/为共享订阅前缀,JQTAHMCSM才是真正的topic
        public string topicStr = @"$share/tahmshare/JQTAHMCSM";  
        
        //用来存储消息
        public Dictionary<string,string> topicDic=new Dictionary<string, string>();

        public void MqttConnectAsync()
        {
            try
            {
                mqttIsConnected = false;

                var mqttFactory = new MqttFactory();

                //使用Build构建
                var mqttClientOptions = new MqttClientOptionsBuilder()
                    .WithTcpServer(serverip, serverport)
                    .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
                    .WithClientId(Guid.NewGuid().ToString())
                    .WithCleanSession(false)
                    .WithKeepAlivePeriod(TimeSpan.FromSeconds(KeepAliveSecond))
                    .WithCredentials(useridstr, passstr)
                    .WithTimeout(TimeSpan.FromSeconds(KeepAliveSecond))
                    //.WithWillTopic(topicStr)
                    .Build();

                mqttClient = mqttFactory.CreateMqttClient();
                //与3.1对比,事件订阅名称和接口已经变化
                mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;
                mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
                mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
                Task task = mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
                task.Wait();
               
                mqttIsConnected = mqttClient.IsConnected;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Mqtt客户端尝试连接出错:{ex.Message}");
            }
        }
        public Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            string text = ToHexString(arg.ApplicationMessage.Payload);
            string Topic = arg.ApplicationMessage.Topic;
            string QoS = arg.ApplicationMessage.QualityOfServiceLevel.ToString();
            string Retained = arg.ApplicationMessage.Retain.ToString();
            topicDic.Add(Topic, text);

            return Task.CompletedTask;
        }

        public Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            Console.WriteLine($"Mqtt客户端连接成功."); // 这里是随便写的,可以写到自己的日志机制
            return Task.CompletedTask;
        }

        public Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            Console.WriteLine($"Mqtt客户端连接断开");// 这里是随便写的,可以写到自己的日志机制
            return Task.CompletedTask;
        }

        public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "
        {

            string hexString = string.Empty;

            if (bytes != null)

            {

                StringBuilder strB = new StringBuilder();

                for (int i = 0; i < bytes.Length; i++)

                {

                    strB.Append(bytes[i].ToString("X2"));

                }

                hexString = strB.ToString();

            }

            return hexString;

        }
    }
}

3、form1中新建一个按钮,用来启动连接和产生mqtt订阅 ,新建一个richtextbox控件用来展示收到的消息。 新建一个定时器,用来定时从帮助类的存储消息的变量中topicDic 取出消息,追加到 tb_mqttMsg

 MqttNetHelper mymqtt = new MqttNetHelper();
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
           
            mymqtt.MqttConnectAsync();
            //mymqtt.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;

            string payload = "hello,from pascalming!";
            string mqttTopic = "/topic/pascalming/v1";
            var applicationMessage = new MqttApplicationMessageBuilder()
                .WithTopic(mqttTopic)
                .WithPayload(payload)
                .Build();
            Task<MqttClientSubscribeResult> task = mymqtt.mqttClient.SubscribeAsync(mymqtt.topicStr); 
            task.Wait(); 
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (mymqtt.mqttIsConnected)
            {
                foreach (var dic in mymqtt.topicDic)
                {
                    tb_mqttMsg.AppendText(dic.Key + "-" + dic.Value + "\r\n");
                    mymqtt.topicDic.Remove(dic.Key);
                }
            }
        }

4、效果如下

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值