微软官方从.Net Core开始,对跨平台支持越来越多,让更多的.Net 开发者可以将.Net程序部署在Linux上,而不局限于Windows服务器。也让C#重新火了一把。但是国内.Net 鼻祖博客园的没落,微软也没救他,这门技术何去何从令人深思。
越讲越远跑题了。从程序员鄙视链来讲,C#可能处于底端,但其简单的写法,让非常多的人所喜欢。本文通过几行简单的代码,让普通人也可以很容易写一个MQTT Windows端收发程序,结合上一篇文章https://forum.eepw.com.cn/thread/391360/1
让MQTT不只局限于Demo软件和单片机的MQTT库。
从界面来看,可以从左侧拖拽出控件,进行图形化编辑。也可以通过XAML写控件。
<Window x:Class="mqtt_test.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:mqtt_test" mc:Ignorable="d" Title="MQTT收发工具" Height="378" Width="720"> <Grid Margin="17,0,0,0" HorizontalAlignment="Left" Width="662" Height="339" VerticalAlignment="Top"> <Grid.ColumnDefinitions> <ColumnDefinition Width="21*"/> <ColumnDefinition Width="443*"/> <ColumnDefinition Width="0*"/> </Grid.ColumnDefinitions> <Button x:Name="btnConnect_Click" Content="连接MQTT服务器" HorizontalAlignment="Left" Margin="6,38,0,0" VerticalAlignment="Top" Height="52" Width="157" Click="btnConnect_Click_1" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1" /> <Label x:Name="lbl_status" Content="状态" HorizontalAlignment="Left" Margin="186,50,0,0" VerticalAlignment="Top" Height="40" Width="417" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1"/> <TextBox x:Name="tbx_msg" HorizontalAlignment="Left" Margin="115,177,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="497" Height="126" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1"/> <Label x:Name="lbl_sub_msg" Content="监听内容" HorizontalAlignment="Left" Margin="6,177,0,0" VerticalAlignment="Top" Height="34" Width="109" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1"/> <TextBox x:Name="tbx_topic" HorizontalAlignment="Left" Margin="115,125,0,0" TextWrapping="Wrap" Text="/test/topic" VerticalAlignment="Top" Width="497" Height="30" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1"/> <Label x:Name="lbl_pub" Content="主题" HorizontalAlignment="Left" Margin="6,125,0,0" VerticalAlignment="Top" Height="30" Width="62" FontFamily="Consolas" FontWeight="Bold" FontSize="20" Grid.Column="1"/> </Grid> </Window>
这里用到了MQTTNET库
通过Nuget管理工具进行下载引用即可
新建一个类文件,命名为MqttUtil.cs
using System; using System.Text; using System.Threading; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; //using MQTTnet.Client.Options; public class MqttUtil { private IMqttClient _mqttClient; private MqttClientOptions _options; public event Action<string> OnMessageReceived; // 事件通知 UI 线程更新 public MqttUtil(string broker, int port, string clientId = "wpf_client") { var mqttFactory = new MqttFactory(); _mqttClient = mqttFactory.CreateMqttClient(); _options = new MqttClientOptionsBuilder() .WithClientId(clientId) .WithTcpServer(broker, port) .WithCleanSession() .Build(); // 消息接收回调 _mqttClient.ApplicationMessageReceivedAsync += e => { string payload = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment); OnMessageReceived?.Invoke($"[{e.ApplicationMessage.Topic}] {payload}"); return Task.CompletedTask; }; // 断开连接回调 _mqttClient.DisconnectedAsync += async e => { Console.WriteLine("MQTT 连接已断开,尝试重新连接..."); await Task.Delay(5000); await _mqttClient.ConnectAsync(_options, CancellationToken.None); }; } public async Task ConnectAsync() { if (!_mqttClient.IsConnected) { await _mqttClient.ConnectAsync(_options, CancellationToken.None); Console.WriteLine("已连接到 MQTT 服务器"); } } public async Task SubscribeAsync(string topic) { if (_mqttClient.IsConnected) { await _mqttClient.SubscribeAsync(topic); Console.WriteLine($"已订阅: {topic}"); } } public async Task PublishAsync(string topic, string message) { if (_mqttClient.IsConnected) { var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic(topic) .WithPayload(message) .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce) .Build(); await _mqttClient.PublishAsync(mqttMessage); Console.WriteLine($"已发送消息: {message} -> {topic}"); } } }
在页面文件对应的C#程序页面写一点内容
using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace mqtt_test { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private MqttUtil _mqttUtil; public MainWindow() { InitializeComponent(); _mqttUtil = new MqttUtil("127.0.0.1", 1883); _mqttUtil.OnMessageReceived += UpdateTextBox; } private void UpdateTextBox(string message) { Dispatcher.Invoke(() => { tbx_msg.Text += message + "\n"; }, DispatcherPriority.Background); } private async void btnConnect_Click_1(object sender, RoutedEventArgs e) { await _mqttUtil.ConnectAsync(); lbl_status.Content += "已连接到 MQTT 服务器并订阅主题\n"; } } }
这样,最简单的一个MQTT 测试程序就写完了,只要电脑安装了.Net 6.0就可以直接运行。