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的属性值了。

相关推荐
西瓜本瓜@6 分钟前
在Android开发中实现静默拍视频
android·java·开发语言·学习·音视频
_.Switch11 分钟前
高效网络自动化:Python在网络基础中的应用
运维·开发语言·网络·python·数据分析·自动化
清灵xmf20 分钟前
JavaScript 中如何识别异步函数?
开发语言·javascript·async·异步函数
七月巫山晴36 分钟前
QChart中柱形图的简单使用并实现【Qt】
开发语言·数据结构·c++·qt·算法·排序算法
阿丁小哥39 分钟前
【Python各个击破】numpy
开发语言·python·numpy
琼火hu1 小时前
R语言笔记(五):Apply函数
开发语言·笔记·r语言·apply
柴头物联网1 小时前
XQT_UI 组件|01|颜色
开发语言·qt·ui
浪漫主义狗1 小时前
JDK源码系列(二)—— ArrayList 和 LinkedList 深度源码解析
java·开发语言·windows·源码
繁依Fanyi1 小时前
ArrayList和linkedList的区别
java·开发语言·算法
achaoyang2 小时前
【Python学习计算机知识储备】
开发语言·python·学习