文章目录
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的属性值了。