C#订阅mqtt主题

文章目录

C#订阅mqtt主题

MQTT搭建

涉及到MQTT服务器的搭建和主题发布,请看这篇文章Windows系统搭建MQTT服务器和安装MQTTX客户端_windows mqttx的安装使用-CSDN博客即可。

创建一个C#项目

文章中用到的代码在这里可以找到:

通过百度网盘分享的文件:C#MQTT.zip

链接:https://pan.baidu.com/s/1fK7kvo2ZPR88Ve3sBGy4wQ

提取码:8778

--来自百度网盘超级会员V5的分享

这里以创建一个wpf项目为例子,进行说明



安装MQTTnet

要订阅mqtt相关的内容,我们需要下载一个C#的包MQTTNet客户端。

这里安装的是MQTTnet4.3.7.1207这个版本。

安装成功之后,在已安装的选型中,可以找到对应的安装内容。

也可以在右侧对应的选项中,确认是否已经安装了MQTTnet这个客户端。

双击按钮,可以跳转到对应的C#代码位置。

代码

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using MQTTnet.Client;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet;

namespace MqttHelloWorld
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // mqtt连接客户端,这里添加一个?是声明可为null
        IMqttClient? mqttClient;
        public MainWindow()
        {
            InitializeComponent();
        }
        /**
         * 订阅消息按钮
         */
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            // Console.WriteLine("订阅消息==========================================订阅消息");
            System.Diagnostics.Debug.WriteLine("订阅消息==========================================订阅消息");

            
            // 这一个判断是,为了保证只建立一个连接,如果去掉,每点击一次订阅主题按钮,建立一个连接。
            // 到时候,就是多个连接了
            if (mqttClient != null)
            {
                // 取消连接
                await mqttClient.DisconnectAsync();
                mqttClient = null;

            }

            var factory = new MqttFactory();
            mqttClient = factory.CreateMqttClient();
            var options = new MqttClientOptionsBuilder()
                  //.WithClientId("mqtttest") // 这里设置MQTT的连接的客户端id,这一步使用自动生成的字符串,也可以自定义
                  .WithTcpServer("127.0.0.1", 1883) // MQTT代理地址和端口
                                                    // .WithCredentials("admin", "public") // 如果MQTT服务器开启了匿名访问,这一句可以直接省略
                  .Build();
            // // 这个await不能省略,否则就有可能连接MQTT服务器失败,添加了await就需要在方法/函数上加async
            await mqttClient.ConnectAsync(options);

            var suboption = new MqttClientSubscribeOptions()
            {
                TopicFilters = new List<MqttTopicFilter>
                {
                    new MqttTopicFilterBuilder()
                        .WithTopic("zheshizhuti") // 这里设置订阅的主题,"#" 是一个通配符,代表订阅所有主题
                        .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // 设置QoS级别为至少一次
                        .Build()
                }
            };
            // 这个await不能省略,否则就是订阅不了,添加了await就需要在方法/函数上加async
            await mqttClient.SubscribeAsync(suboption);

            mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;


        }

        private Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            System.Diagnostics.Debug.WriteLine("====================这个是订阅的主题消息======================");
            System.Diagnostics.Debug.WriteLine(arg.ApplicationMessage.ConvertPayloadToString());
            System.Diagnostics.Debug.WriteLine("====================这个是订阅的主题消息======================");
            return null;
        }

        /**
        * 取消订阅消息按钮
        */
        private async void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (mqttClient != null)
            {
                await mqttClient.UnsubscribeAsync("zheshizhuti");
                System.Diagnostics.Debug.WriteLine("取消订阅消息++++++++++++++++++++++++++++++++++++取消订阅消息");
                // 取消连接
                await mqttClient.DisconnectAsync();

                mqttClient = null;

            }
            
        }
    }
}

运行成功之后

清除日志之后,就可以跟方便在控制台中看后面订阅的主题内容了。

确认是否连接成功

确认是否连接成功了,登录emqx的管理界面。

使用MQTTX客户端发布主题内容






订阅成功了但是没有收到消息

这里我遇到过一个问题,就是明明订阅成功了,但是在MqttClient_ApplicationMessageReceivedAsync这个方法/函数中(具体看后面的代码)。就是收不到发布的主题信息内容,打断点也不行,程序运行也不报错。发现这个问题,是因为我想将字符串转换成JSON数据,然后拿到某个字段属性的值。那么造成这个问题的原因是什么呢?问题就是我引用了Newtonsoft.Json这个包。

这个是在.net4.8版本的时候遇到的情况,在.net6版本,并没有这个问题,也能正常订阅,拿到消息。后面是怎么解决的呢?我把Newtonsoft.Josn这个库删除了,不用它了。我使用了另外一个C#的JSON库,如果你使用的是.NET Core.NET 5/6/7等新版框架,可能需要通过NuGet包管理器安装Microsoft.Extensions.Json包来使用Json.NET,也就是内置了System.Text.Json这个库。因为低版本没有内置这个库,所以我是使用安装的方式引用的,但是在.net6中可以直接使用,不需要下载什么包之类的。因为这里使用的是高版本的.net6,所以两种方式都可以。

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using MQTTnet.Client;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet;
using Newtonsoft.Json.Linq;
using System.Text.Json;

namespace MqttHelloWorld
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // mqtt连接客户端,这里添加一个?是声明可为null
        IMqttClient? mqttClient;
        public MainWindow()
        {
            InitializeComponent();
        }
        /**
         * 订阅消息按钮
         */
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            // Console.WriteLine("订阅消息==========================================订阅消息");
            System.Diagnostics.Debug.WriteLine("订阅消息==========================================订阅消息");

            
            // 这一个判断是,为了保证只建立一个连接,如果去掉,每点击一次订阅主题按钮,建立一个连接。
            // 到时候,就是多个连接了
            if (mqttClient != null)
            {
                // 取消连接
                await mqttClient.DisconnectAsync();
                mqttClient = null;

            }

            var factory = new MqttFactory();
            mqttClient = factory.CreateMqttClient();
            var options = new MqttClientOptionsBuilder()
                  //.WithClientId("mqtttest") // 这里设置MQTT的连接的客户端id,这一步使用自动生成的字符串,也可以自定义
                  .WithTcpServer("127.0.0.1", 1883) // MQTT代理地址和端口
                                                    // .WithCredentials("admin", "public") // 如果MQTT服务器开启了匿名访问,这一句可以直接省略
                  .Build();
            // // 这个await不能省略,否则就有可能连接MQTT服务器失败,添加了await就需要在方法/函数上加async
            await mqttClient.ConnectAsync(options);

            var suboption = new MqttClientSubscribeOptions()
            {
                TopicFilters = new List<MqttTopicFilter>
                {
                    new MqttTopicFilterBuilder()
                        .WithTopic("zheshizhuti") // 这里设置订阅的主题,"#" 是一个通配符,代表订阅所有主题
                        .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce) // 设置QoS级别为至少一次
                        .Build()
                }
            };
            // 这个await不能省略,否则就是订阅不了,添加了await就需要在方法/函数上加async
            await mqttClient.SubscribeAsync(suboption);

            mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;


        }

        private Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
        {
            System.Diagnostics.Debug.WriteLine("====================这个是订阅的主题消息======================");
            System.Diagnostics.Debug.WriteLine(arg.ApplicationMessage.ConvertPayloadToString());
            var message = arg.ApplicationMessage.ConvertPayloadToString();

            JObject json = JObject.Parse(message);
            string msg1 = json["msg"].ToString();
            System.Diagnostics.Debug.WriteLine("这是内容msg1:====》" + msg1);

            var jsons = JsonDocument.Parse(message);
            var msg2 = jsons.RootElement.GetProperty("msg");
            System.Diagnostics.Debug.WriteLine("这是内容msg2:====》" + msg2);

            System.Diagnostics.Debug.WriteLine("====================这个是订阅的主题消息======================");
            return null;
        }

        /**
        * 取消订阅消息按钮
        */
        private async void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (mqttClient != null)
            {
                await mqttClient.UnsubscribeAsync("zheshizhuti");
                System.Diagnostics.Debug.WriteLine("取消订阅消息++++++++++++++++++++++++++++++++++++取消订阅消息");
                // 取消连接
                await mqttClient.DisconnectAsync();

                mqttClient = null;

            }
            
        }
    }
}

可以看到能够,正常拿到内容了,拿到对应JSON的属性值了。

相关推荐
SmoothSailingT18 小时前
C#——Lazy<T>懒加载机制
开发语言·单例模式·c#·懒加载
程序喵大人18 小时前
SQLITE问题整理
开发语言·数据库·c++·sqlite
Neolnfra18 小时前
文件包含漏洞终极指南
开发语言·安全·web安全·网络安全·系统安全·php·可信计算技术
简单点好不好18 小时前
2025--简单点--python之状态模式
开发语言·python·状态模式
czhc114007566318 小时前
c# 1216
windows·microsoft·c#
1+2单片机电子设计18 小时前
基于 STM32 的网络授权时钟系统设计与实现
开发语言·stm32·单片机·嵌入式硬件·php·51单片机
Tjohn918 小时前
Java环境配置(JDK8环境变量配置)补充
java·开发语言
摇摆的含羞草18 小时前
Java加解密相关的各种名词的含义,各种分类的算法及特点
java·开发语言·算法
天桥下的卖艺者18 小时前
R语言绘制复杂加权数据(nhanes数据)多模型生存分析决策曲线
开发语言·r语言
huohuopro18 小时前
java金额转换,将数字金额转换为7位大写
java·开发语言