C#使用MQTT(二):MQTT客户端

2 篇文章 0 订阅

上一篇我们初步设计了MQTT服务端

C#使用MQTT(一):MQTT服务端-CSDN博客

这里我们设计客户端MQTT Client,接上一篇

新建Windows窗体FormMqttClient

窗体FormMqttClient设计如图:

窗体FormMqttClient设计器相关代码如下

文件FormMqttClient.Designer.cs


namespace CultureDemo
{
    partial class FormMqttClient
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.rtxtMessage = new System.Windows.Forms.RichTextBox();
            this.label8 = new System.Windows.Forms.Label();
            this.btnPublish = new System.Windows.Forms.Button();
            this.btnSubscribe = new System.Windows.Forms.Button();
            this.txtContent = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.txtTopicPublish = new System.Windows.Forms.TextBox();
            this.label6 = new System.Windows.Forms.Label();
            this.txtTopic = new System.Windows.Forms.TextBox();
            this.label7 = new System.Windows.Forms.Label();
            this.btnDisconnect = new System.Windows.Forms.Button();
            this.btnConnect = new System.Windows.Forms.Button();
            this.txtClientId = new System.Windows.Forms.TextBox();
            this.label4 = new System.Windows.Forms.Label();
            this.txtUpwd = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.txtUserName = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.txtPort = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.txtIP = new System.Windows.Forms.TextBox();
            this.lb = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // rtxtMessage
            // 
            this.rtxtMessage.Location = new System.Drawing.Point(239, 37);
            this.rtxtMessage.Name = "rtxtMessage";
            this.rtxtMessage.Size = new System.Drawing.Size(623, 411);
            this.rtxtMessage.TabIndex = 51;
            this.rtxtMessage.Text = "";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.Location = new System.Drawing.Point(242, 18);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(29, 12);
            this.label8.TabIndex = 50;
            this.label8.Text = "消息";
            // 
            // btnPublish
            // 
            this.btnPublish.Location = new System.Drawing.Point(117, 425);
            this.btnPublish.Name = "btnPublish";
            this.btnPublish.Size = new System.Drawing.Size(75, 23);
            this.btnPublish.TabIndex = 49;
            this.btnPublish.Text = "发布";
            this.btnPublish.UseVisualStyleBackColor = true;
            this.btnPublish.Click += new System.EventHandler(this.btnPublish_Click);
            // 
            // btnSubscribe
            // 
            this.btnSubscribe.Location = new System.Drawing.Point(117, 286);
            this.btnSubscribe.Name = "btnSubscribe";
            this.btnSubscribe.Size = new System.Drawing.Size(75, 23);
            this.btnSubscribe.TabIndex = 48;
            this.btnSubscribe.Text = "订阅";
            this.btnSubscribe.UseVisualStyleBackColor = true;
            this.btnSubscribe.Click += new System.EventHandler(this.btnSubscribe_Click);
            // 
            // txtContent
            // 
            this.txtContent.Location = new System.Drawing.Point(92, 377);
            this.txtContent.Name = "txtContent";
            this.txtContent.Size = new System.Drawing.Size(100, 21);
            this.txtContent.TabIndex = 47;
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(45, 380);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(29, 12);
            this.label5.TabIndex = 46;
            this.label5.Text = "内容";
            // 
            // txtTopicPublish
            // 
            this.txtTopicPublish.Location = new System.Drawing.Point(92, 341);
            this.txtTopicPublish.Name = "txtTopicPublish";
            this.txtTopicPublish.Size = new System.Drawing.Size(100, 21);
            this.txtTopicPublish.TabIndex = 45;
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Location = new System.Drawing.Point(45, 344);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(29, 12);
            this.label6.TabIndex = 44;
            this.label6.Text = "主题";
            // 
            // txtTopic
            // 
            this.txtTopic.Location = new System.Drawing.Point(92, 248);
            this.txtTopic.Name = "txtTopic";
            this.txtTopic.Size = new System.Drawing.Size(100, 21);
            this.txtTopic.TabIndex = 43;
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.Location = new System.Drawing.Point(45, 251);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(29, 12);
            this.label7.TabIndex = 42;
            this.label7.Text = "主题";
            // 
            // btnDisconnect
            // 
            this.btnDisconnect.Location = new System.Drawing.Point(130, 205);
            this.btnDisconnect.Name = "btnDisconnect";
            this.btnDisconnect.Size = new System.Drawing.Size(75, 23);
            this.btnDisconnect.TabIndex = 41;
            this.btnDisconnect.Text = "断开";
            this.btnDisconnect.UseVisualStyleBackColor = true;
            this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
            // 
            // btnConnect
            // 
            this.btnConnect.Location = new System.Drawing.Point(36, 205);
            this.btnConnect.Name = "btnConnect";
            this.btnConnect.Size = new System.Drawing.Size(75, 23);
            this.btnConnect.TabIndex = 40;
            this.btnConnect.Text = "连接";
            this.btnConnect.UseVisualStyleBackColor = true;
            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
            // 
            // txtClientId
            // 
            this.txtClientId.Location = new System.Drawing.Point(67, 164);
            this.txtClientId.Name = "txtClientId";
            this.txtClientId.Size = new System.Drawing.Size(134, 21);
            this.txtClientId.TabIndex = 39;
            this.txtClientId.Text = "snake";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(20, 167);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(41, 12);
            this.label4.TabIndex = 38;
            this.label4.Text = "客户ID";
            // 
            // txtUpwd
            // 
            this.txtUpwd.Location = new System.Drawing.Point(67, 127);
            this.txtUpwd.Name = "txtUpwd";
            this.txtUpwd.Size = new System.Drawing.Size(134, 21);
            this.txtUpwd.TabIndex = 37;
            this.txtUpwd.Text = "1";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(32, 130);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(29, 12);
            this.label3.TabIndex = 36;
            this.label3.Text = "密码";
            // 
            // txtUserName
            // 
            this.txtUserName.Location = new System.Drawing.Point(67, 100);
            this.txtUserName.Name = "txtUserName";
            this.txtUserName.Size = new System.Drawing.Size(134, 21);
            this.txtUserName.TabIndex = 35;
            this.txtUserName.Text = "a";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(32, 103);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(29, 12);
            this.label2.TabIndex = 34;
            this.label2.Text = "账号";
            // 
            // txtPort
            // 
            this.txtPort.Location = new System.Drawing.Point(67, 64);
            this.txtPort.Name = "txtPort";
            this.txtPort.Size = new System.Drawing.Size(134, 21);
            this.txtPort.TabIndex = 33;
            this.txtPort.Text = "12345";
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(32, 67);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(29, 12);
            this.label1.TabIndex = 32;
            this.label1.Text = "端口";
            // 
            // txtIP
            // 
            this.txtIP.Location = new System.Drawing.Point(67, 22);
            this.txtIP.Name = "txtIP";
            this.txtIP.Size = new System.Drawing.Size(134, 21);
            this.txtIP.TabIndex = 31;
            this.txtIP.Text = "127.0.0.1";
            // 
            // lb
            // 
            this.lb.AutoSize = true;
            this.lb.Location = new System.Drawing.Point(20, 25);
            this.lb.Name = "lb";
            this.lb.Size = new System.Drawing.Size(41, 12);
            this.lb.TabIndex = 30;
            this.lb.Text = "IP地址";
            // 
            // FormMqttClient
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(874, 525);
            this.Controls.Add(this.rtxtMessage);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.btnPublish);
            this.Controls.Add(this.btnSubscribe);
            this.Controls.Add(this.txtContent);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.txtTopicPublish);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.txtTopic);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.btnDisconnect);
            this.Controls.Add(this.btnConnect);
            this.Controls.Add(this.txtClientId);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.txtUpwd);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.txtUserName);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.txtPort);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.txtIP);
            this.Controls.Add(this.lb);
            this.Name = "FormMqttClient";
            this.Text = "FormMqttClient";
            this.Load += new System.EventHandler(this.FormMqttClient_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.RichTextBox rtxtMessage;
        private System.Windows.Forms.Label label8;
        private System.Windows.Forms.Button btnPublish;
        private System.Windows.Forms.Button btnSubscribe;
        private System.Windows.Forms.TextBox txtContent;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.TextBox txtTopicPublish;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.TextBox txtTopic;
        private System.Windows.Forms.Label label7;
        private System.Windows.Forms.Button btnDisconnect;
        private System.Windows.Forms.Button btnConnect;
        private System.Windows.Forms.TextBox txtClientId;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox txtUpwd;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.TextBox txtUserName;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox txtPort;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox txtIP;
        private System.Windows.Forms.Label lb;
    }
}

窗体FormMqttClient程序代码如下:客户端程序

文件FormMqttClient.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MQTTnet;
using MQTTnet.Client;

namespace CultureDemo
{
    public partial class FormMqttClient : Form
    {
        IMqttClient mqttClient;
        public FormMqttClient()
        {
            InitializeComponent();
            rtxtMessage.ReadOnly = true;
        }

        /// <summary>
        /// 打印相关消息
        /// </summary>
        /// <param name="contents"></param>
        private void DisplayMessage(string contents)
        {
            if (!this.IsHandleCreated)
            {
                return;
            }
            this.BeginInvoke(new Action(() =>
            {
                if (rtxtMessage.TextLength >= 40960)
                {
                    rtxtMessage.Clear();
                }
                rtxtMessage.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}->{contents}\n");
                rtxtMessage.ScrollToCaret();
            }));
        }

        private void FormMqttClient_Load(object sender, EventArgs e)
        {
            mqttClient = new MqttFactory().CreateMqttClient();
            mqttClient.ConnectedAsync += MqttClient_ConnectedAsync;
            mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;
            mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
        }

        private Task MqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
        {
            return Task.Run(new Action(() =>
            {
                string msg = e.ApplicationMessage.ConvertPayloadToString();
                DisplayMessage($"接收消息:{msg}\nQoS={e.ApplicationMessage.QualityOfServiceLevel}\n客户端={e.ClientId}\n主题:{e.ApplicationMessage.Topic}");
            }));
        }

        private Task MqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs e)
        {
            return Task.Run(new Action(async () =>
            {
                DisplayMessage($"已断开到MQTT服务端的连接.尝试重新连接");
                try
                {
                    await Task.Delay(3000);
                    //MqttClientOptions options = new MqttClientOptions();
                    //await mqttClient.ConnectAsync(options);
                    await mqttClient.ReconnectAsync();
                }
                catch (Exception ex)
                {
                    DisplayMessage($"重新连接服务器失败:{ex.Message}");
                }
            }));
        }

        private Task MqttClient_ConnectedAsync(MqttClientConnectedEventArgs e)
        {
            return Task.Run(new Action(() =>
            {
                DisplayMessage($"连接到MQTT服务端成功.{e.ConnectResult.AssignedClientIdentifier}");
            }));
        }

        private async void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                MqttClientOptionsBuilder mqttClientOptionBuild = new MqttClientOptionsBuilder()
                 .WithClientId(this.txtClientId.Text)
                 .WithTcpServer(this.txtIP.Text, int.Parse(this.txtPort.Text))
                 .WithCredentials(this.txtUserName.Text, this.txtUpwd.Text);
                MqttClientOptions options = mqttClientOptionBuild.Build();
                //开启
                await mqttClient.ConnectAsync(options);
            }
            catch (Exception ex) 
            {
                DisplayMessage($"连接服务端时出现异常:{ex.Message}");
            }
        }

        private async void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (mqttClient != null)
            {
                if (mqttClient.IsConnected)
                {
                    await mqttClient.DisconnectAsync();
                }
                mqttClient.Dispose();
            }
        }

        private async void btnSubscribe_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.txtTopic.Text))
            {
                DisplayMessage(">>> 请输入主题");
                return;
            }
            //在 MQTT 中有三种 QoS 级别: QuanlityOfService
            //At most once(0) 最多一次
            //At least once(1) 至少一次
            //Exactly once(2) 恰好一次
            MqttClientSubscribeOptionsBuilder subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder();
            MqttClientSubscribeOptions subscribeOption = subscribeOptionsBuilder.WithTopicFilter(this.txtTopic.Text).Build();
            await mqttClient.SubscribeAsync(subscribeOption);
            DisplayMessage($">>> 成功订阅主题【{txtTopic.Text}】");
        }

        private async void btnPublish_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.txtTopicPublish.Text))
            {
                DisplayMessage(">>> 请输入主题");
                return;
            }
            MqttClientPublishResult result = await mqttClient.PublishStringAsync(
                this.txtTopicPublish.Text,
                this.txtContent.Text,
                MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce);//恰好一次, QoS 级别1   
            DisplayMessage($"发布消息--主题:{this.txtTopicPublish.Text},消息:{this.txtContent.Text},结果: {result.ReasonCode}");
        }
    }
}

为了一个应用程序可以作为客户端和服务端,我们在Program.cs增加切换开关

选择作为MQTT服务端和MQTT客户端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CultureDemo
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            DialogResult dialog = MessageBox.Show("请选择程序作为MQTT服务端还是客户端,选择\"是\"作为服务端,选择\"否\"作为客户端", "是否MQTT服务端", MessageBoxButtons.YesNo);
            if (dialog == DialogResult.Yes)
            {
                Application.Run(new FormMqttServer());
            }
            else 
            {
                Application.Run(new FormMqttClient());
            }
        }
    }
}

程序运行如图:

运行客户端与服务端通信

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是使用 C# 编写 MQTT 客户端的示例代码,需要使用 MQTTnet 库: ```csharp using System; using System.Text; using System.Threading; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; namespace MqttClientDemo { class Program { static async Task Main(string[] args) { var factory = new MqttFactory(); var client = factory.CreateMqttClient(); var options = new MqttClientOptionsBuilder() .WithTcpServer("broker.emqx.io") .WithClientId("MqttClientDemo") .WithCredentials("username", "password") .WithCleanSession() .Build(); await client.ConnectAsync(options); Console.WriteLine("连接到 MQTT 服务器成功!"); var topic = new MqttTopicFilterBuilder() .WithTopic("topic/test") .Build(); await client.SubscribeAsync(topic); Console.WriteLine("订阅主题成功!"); client.UseApplicationMessageReceivedHandler(e => { Console.WriteLine($"接收到主题:{e.ApplicationMessage.Topic},消息:{Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); }); while (true) { Console.Write("请输入要发布的消息:"); var message = Console.ReadLine(); var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic("topic/test") .WithPayload(message) .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await client.PublishAsync(mqttMessage); Console.WriteLine("消息发送成功!"); } } } } ``` 在上述示例代码中,我们使用 MQTTnet 库创建了一个 MQTT 客户端,并连接到了一个公共的 MQTT 服务器(broker.emqx.io)。我们订阅了一个主题(topic/test),并使用 `UseApplicationMessageReceivedHandler` 方法处理接收到的消息。同时,我们还可以使用 `MqttApplicationMessageBuilder` 创建一个 MQTT 消息,并使用 `PublishAsync` 方法将其发布到指定的主题。 需要注意的是,在实际应用中,我们需要根据实际的业务需求,选择合适的 MQTT 服务器和主题,以及正确的连接方式、QoS 等参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值