C#MQTT协议应用

1 ,MQTT介绍:
MQTT详解以及实际操作_mqtt使用-CSDN博客

2,MQTT应用:

C#MQTT编程06--MQTT服务器和客户端(winform版)_c# mqtt服务器-CSDN博客

3,MQTT实例:

 

效果 

代码:

服务端

  public partial class Form1 : Form{Timer timer = new Timer();List<ClientItem> clients = new List<ClientItem>();public Form1(){InitializeComponent();timer.Interval = 500;timer.Tick += Timer_Tick;timer.Start();InitSetting();}private void Timer_Tick(object sender, EventArgs e){toolStripStatusDateTime.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");}void InitSetting(){//获取本机所有的IP4地址string[] ips = Dns.GetHostAddresses(Environment.MachineName).Where(item => !item.IsIPv6LinkLocal).Select(item => item.ToString()).ToArray();comboIp_List.DataSource = ips;txtPort.Text = "8000";txtUserName.Text = "sa";txtPwd.Text = "1";}IMqttServer mqttServer;private void btnStart_Click(object sender, EventArgs e){if (btnStart.Text.Equals("开始")){IMqttServerOptions options = new MqttServerOptionsBuilder().WithConnectionBacklog(10).WithDefaultEndpointBoundIPAddress(IPAddress.Parse(comboIp_List.Text.Trim())).WithDefaultEndpointPort(Convert.ToInt32(txtPort.Text.Trim())).WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000)).WithConnectionValidator(context =>{//验证if (ck_UserPwd.Checked){if (!context.Username.Equals(txtUserName.Text)){context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.BadUserNameOrPassword;}if (!context.Password.Equals(txtPwd.Text)){context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.BadUserNameOrPassword;}}else{context.ReasonCode = MQTTnet.Protocol.MqttConnectReasonCode.Success;}}).Build();mqttServer = new MqttFactory().CreateMqttServer();mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(ApplicationMessageReceived);//服务开始事件mqttServer.StartedHandler = new MqttServerStartedHandlerDelegate(MqttServer_StartedAsync);//服务停止事件mqttServer.StoppedHandler = new MqttServerStoppedHandlerDelegate(MqttServer_StoppedAsync);//客户端连接事件mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(MqttServer_ClientConnectedAsync);//客户端断开连接事件mqttServer.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(MqttServer_ClientDisconnectedAsync);//客户端订阅事件mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(MqttServer_ClientSubscribedTopicAsync);//客户端取消订阅事件mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttServer_ClientUnsubscribedTopicAsync);mqttServer.StartAsync(options);if (mqttServer.IsStarted){btnStart.Text = "断开";btnStart.BackColor = Color.Green;comboIp_List.Enabled = txtPort.Enabled = false;}}else{mqttServer.StopAsync().Wait();if (!mqttServer.IsStarted){btnStart.Text = "开始";btnStart.BackColor = Color.Red;comboIp_List.Enabled = txtPort.Enabled = true;}mqttServer.Dispose();}}private Task MqttServer_ClientUnsubscribedTopicAsync(MqttServerClientUnsubscribedTopicEventArgs arg){//客户端取消订阅事件string msg = $"客户端ID:[{arg.ClientId}] 取消主题:[{arg.TopicFilter}] 订阅";AddLog(1, msg);//取消订阅ClientItem client = clients.FirstOrDefault(item => item.ClientID.Equals(arg.ClientId));client?.Topics.RemoveAll(item => item.Topic.Equals(arg.TopicFilter));return Task.FromResult(arg);}private Task MqttServer_ClientSubscribedTopicAsync(MqttServerClientSubscribedTopicEventArgs arg){//客户端订阅事件string msg = $"客户端ID:[{arg.ClientId}]订阅主题:[{arg.TopicFilter.Topic}],Qos:[{arg.TopicFilter.QualityOfServiceLevel}]";AddLog(0, msg);TopicItem topic = new TopicItem { QualityOfServiceLevel = arg.TopicFilter.QualityOfServiceLevel, Topic = arg.TopicFilter.Topic };ClientItem client = clients.FirstOrDefault(item => item.ClientID.Equals(arg.ClientId));client?.Topics.Add(topic);return Task.FromResult(arg);}private Task MqttServer_ClientDisconnectedAsync(MqttServerClientDisconnectedEventArgs arg){//客户端断开事件string msg = $"客户端ID:[{arg.ClientId}] 断开连接,EndPoint:{arg.Endpoint},断开连接类型:{arg.DisconnectType}";AddLog(1, msg);//移除该Clientclients.RemoveAll(item => item.ClientID.Equals(arg.ClientId));//更新ListBoxUpdateClientList();return Task.FromResult(arg);}private Task MqttServer_ClientConnectedAsync(MqttServerClientConnectedEventArgs arg){//客户端连接事件string msg = $"客户端ID:[{arg.ClientId}]连接 ,EndPoint:{arg.Endpoint},UserName: {arg.UserName}";AddLog(0, msg);ClientItem client = new ClientItem{ClientID = arg.ClientId,EndPoint = arg.Endpoint};clients.Add(client);//更新ListBoxUpdateClientList();return Task.FromResult(arg);}private Task ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs arg){//客户端MessageReceived事件string msg = $"收到消息:发送者ID:[{arg.ClientId}] QoS:{arg.ApplicationMessage.QualityOfServiceLevel} topic:{arg.ApplicationMessage.Topic}, 内容:{arg.ApplicationMessage.ConvertPayloadToString()}";AddLog(1, msg);return Task.FromResult(arg);}private Task MqttServer_StoppedAsync(EventArgs arg){//服务停止事件string msg = $"服务停止";AddLog(1, msg);clients.Clear();return Task.FromResult(arg);}private Task MqttServer_StartedAsync(EventArgs arg){//服务开启事件string msg = $"服务开启";AddLog(0, msg);return Task.FromResult(arg);}private void ck_UserPwd_CheckedChanged(object sender, EventArgs e){txtUserName.Enabled = txtPwd.Enabled = ck_UserPwd.Checked;}void AddLog(int cate, string msg){if (lstview_Note.InvokeRequired){this.Invoke(new Action(() =>{ListViewItem item = new ListViewItem();item.ImageIndex = cate;item.SubItems.Add(DateTime.Now.ToString("HH:mm:ss"));item.SubItems.Add(msg);lstview_Note.Items.Add(item);lstview_Note.EnsureVisible(lstview_Note.Items.Count - 1);toolStripStatusConnectCount.Text = clients.Count.ToString();}));}else{ListViewItem item = new ListViewItem();item.ImageIndex = cate;item.SubItems.Add(DateTime.Now.ToString("HH:mm:ss"));item.SubItems.Add(msg);lstview_Note.Items.Add(item);lstview_Note.EnsureVisible(lstview_Note.Items.Count - 1);toolStripStatusConnectCount.Text = clients.Count.ToString();}}private void btnCreateClient_Click(object sender, EventArgs e){ClientFrm frm = new ClientFrm();frm.Show();}private void lst_Client_SelectedIndexChanged(object sender, EventArgs e){if (lst_Client.SelectedItem != null){ClientItem item = lst_Client.SelectedItem as ClientItem;lst_Topic.DataSource = item.Topics.Select(a => $"Topic:{a.Topic},QoS:{a.QualityOfServiceLevel}").ToArray();}}/// <summary>/// 更新clientList 列表/// </summary>void UpdateClientList(){this.Invoke(new Action(() => {lst_Client.Items.Clear();foreach (var item in clients){lst_Client.Items.Add(item);}toolStripStatusConnectCount.Text = clients.Count.ToString();}));}}
 class ClientItem{public List<TopicItem> Topics { get; set; } = new List<TopicItem>();public string ClientID { get; set; }public string EndPoint { get; set; }public override string ToString(){return $"{ClientID};{EndPoint}";}}class TopicItem{public string Topic { get; set; }/// <summary>/// 服务质量级别,QoS0 (Almost One):至多一次,只发送一次,会发生消息丢失或重复。QoS1(Atleast Once): 至少一次,确保消息到达,但消息可能重复发送。QoS2(Exactly Once):只有一次,确保消息只到达一次。/// </summary>public MqttQualityOfServiceLevel QualityOfServiceLevel { get; set; }}

客户端

 public partial class ClientFrm : Form{Timer timer = new Timer();public ClientFrm(){InitializeComponent();timer.Interval = 500;timer.Tick += Timer_Tick;timer.Start();InitSetting();}private void Timer_Tick(object sender, EventArgs e){toolStripStatusDateTime.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");}void InitSetting(){//获取本机所有的IP4地址string[] ips = Dns.GetHostAddresses(Environment.MachineName).Where(item => !item.IsIPv6LinkLocal).Select(item => item.ToString()).ToArray();comboIp_List.DataSource = ips;txtPort.Text = "8000";txtUserName.Text = "sa";txtPwd.Text = "1";comboQoS.DataSource = Enum.GetNames(typeof(MQTTnet.Protocol.MqttQualityOfServiceLevel));}IMqttClient client;private void btnConnect_Click(object sender, EventArgs e){//  txtClientId.Text = Guid.NewGuid().ToString();if (string.IsNullOrEmpty(txtClientId.Text.Trim())){MessageBox.Show("ClientId不能为空!");return;}if (btnConnect.Text.Equals("连接")){client = new MqttFactory().CreateMqttClient();MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder().WithClientId(txtClientId.Text.Trim()).WithCommunicationTimeout(TimeSpan.FromMilliseconds(50000)).WithTcpServer(comboIp_List.Text.Trim(), Convert.ToInt32(txtPort.Text.Trim()));if (ck_UserPwd.Checked){builder.WithCredentials(txtUserName.Text.Trim(), txtPwd.Text.Trim());}IMqttClientOptions option = builder.Build();//消息接收事件client.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(Client_ApplicationMessageReceivedAsync);//客户端连接事件client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(Client_ConnectedAsync);// client.UseConnectedHandler//客户端连接断开事件client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(Client_DisconnectedAsync);client.ConnectAsync(option);}else{client.DisconnectAsync().Wait();UpdateStatus(client.IsConnected);client.Dispose();}}private Task Client_DisconnectedAsync(MqttClientDisconnectedEventArgs arg){//客户端断开事件string msg = $" 断开连接, 返回结果:{arg.Reason}";AddLog(1, msg);UpdateStatus(client.IsConnected);return Task.FromResult(arg);}private Task Client_ConnectedAsync(MqttClientConnectedEventArgs arg){//客户端连接事件string msg = $"客户端ID 连接,结果:{arg.ConnectResult.ResultCode}";AddLog(0, msg);UpdateStatus(client.IsConnected);return Task.FromResult(arg);}private Task Client_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg){//客户端取消订阅事件string msg = $"消息ClientId:[{arg.ClientId}] , topic:[{arg.ApplicationMessage.Topic}], 内容:[{arg.ApplicationMessage.ConvertPayloadToString()}],QoS:[{arg.ApplicationMessage.QualityOfServiceLevel}]";AddLog(1, msg);return Task.FromResult(arg);}private void ck_UserPwd_CheckedChanged(object sender, EventArgs e){txtUserName.Enabled = txtPwd.Enabled = ck_UserPwd.Checked;}void AddLog(int cate, string msg){this.Invoke(new Action(() =>{ListViewItem item = new ListViewItem();item.ImageIndex = cate;item.SubItems.Add(DateTime.Now.ToString("HH:mm:ss"));item.SubItems.Add(msg);lstview_Note.Items.Add(item);lstview_Note.EnsureVisible(lstview_Note.Items.Count - 1);}));}private async void btnSubscribed_Click(object sender, EventArgs e){if (string.IsNullOrWhiteSpace(txtTopic.Text)){MessageBox.Show("主题不能为空!");return;}//主题订阅if (client?.IsConnected == true){//QoS0 (Almost One):至多一次,只发送一次,会发生消息丢失或重复。//QoS1(Atleast Once): 至少一次,确保消息到达,但消息可能重复发送//QoS2(Exactly Once):只有一次:只有一次,确保消息只到达一次。var result = await client.SubscribeAsync(new MqttTopicFilter(){QualityOfServiceLevel = (MqttQualityOfServiceLevel)Enum.Parse(typeof(MqttQualityOfServiceLevel), comboQoS.Text.Trim()),Topic = txtTopic.Text.Trim()});StringBuilder sb = new StringBuilder();foreach (var item in result.Items){sb.AppendLine($"订阅主题:[{item.TopicFilter.Topic}],QoS:[{item.TopicFilter.QualityOfServiceLevel}],ReturnCode:[{item.ResultCode}]");}AddLog(0, sb.ToString());}else{MessageBox.Show("请先连接服务!");}}private async void btnPublish_Click(object sender, EventArgs e){if (string.IsNullOrWhiteSpace(txtMsgTopic.Text.Trim())){MessageBox.Show("主题不能为空!");return;}//发布信息if (client?.IsConnected == true){var result = await client.PublishAsync(new MqttApplicationMessage{Topic = txtMsgTopic.Text.Trim(),QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce,Payload =Encoding.UTF8.GetBytes( txtMsgContent.Text.Trim())});string msg = $"发布消息:{txtMsgContent.Text} Topic:{txtMsgTopic.Text.Trim()} 结果:{result.ReasonCode}";AddLog(0, msg);}else{MessageBox.Show("请先连接服务!");}}void UpdateStatus(bool isConnected){this.Invoke(new Action(() =>{if (!isConnected){btnConnect.Text = "连接";btnConnect.BackColor = Color.Red;comboIp_List.Enabled = txtPort.Enabled = true;}else{btnConnect.Text = "断开";btnConnect.BackColor = Color.Green;comboIp_List.Enabled = txtPort.Enabled = false;}}));}private async void btnUnsubscribed_Click(object sender, EventArgs e){if (string.IsNullOrWhiteSpace(txtTopic.Text)){MessageBox.Show("主题不能为空!");return;}//主题订阅if (client?.IsConnected == true){//QoS0 (Almost One):至多一次,只发送一次,会发生消息丢失或重复。//QoS1(Atleast Once): 至少一次,确保消息到达,但消息可能重复发送//QoS2(Exactly Once):只有一次:只有一次,确保消息只到达一次。var result = await client.UnsubscribeAsync(txtTopic.Text.Trim());StringBuilder sb = new StringBuilder();foreach (var item in result.Items){sb.AppendLine($"取消主题:[{item.TopicFilter}]订阅,ReturnCode:[{item.ReasonCode}]");}AddLog(0, sb.ToString());}else{MessageBox.Show("请先连接服务!");}}}

demo链接

https://download.csdn.net/download/lingxiao16888/89616009

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/392189.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过Stack Overflow线程栈溢出的问题实例,详解C++程序线程栈溢出的诸多细节

目录 1、问题说明 2、从Visual Studio输出窗口中找到了线索,发生了Stack Overflow线程栈溢出的异常 3、发生Stack Overflow线程栈溢出的原因分析 4、线程占用的栈空间大小说明 5、引发线程栈溢出的常见原因和场景总结 6、在问题函数入口处添加return语句,在Debug下运行…

TI音频功放TAS6511(二)

3.数字音频处理 芯片支持高级数字音频处理能力&#xff0c;包括&#xff1a; 高通滤波器/直流阻断 数字音量控制 PVDD的Foldback/AGL 热Foldback 双象限增益补偿 混合调制 实时负载诊断 低延迟路径 喇叭功率限制 1&#xff09;PVDD Foldback 本功能主要为了防止音频…

【Material-UI】Autocomplete中的禁用选项:Disabled options

文章目录 一、简介二、基本用法三、进阶用法1. 动态禁用2. 提示禁用原因3. 复杂的禁用条件 四、最佳实践1. 一致性2. 提供反馈3. 优化性能 五、总结 Material-UI的Autocomplete组件提供了丰富的功能&#xff0c;包括禁用特定选项的能力。这一特性对于限制用户选择、提供更好的用…

【你也能从零基础学会网站开发】SQL Server 2000中的数据类型之String字符串类型

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 SQL Server 中…

不用PS也能抠图?点哪抠哪,简直是职场人的最强助手

抠图你还在用 PS 一点点抠吗&#xff1f; 不仅费时费力&#xff0c;还常常达不到理想效果&#xff0c;真的太让人崩溃了 但别担心&#xff0c;我找到了一个超棒的工具——千鹿设计助手的AI智能抠图插件。它就像你的私人设计小助手&#xff0c;能快速帮你把想要的元素抠出来&…

《花100块做个摸鱼小网站! · 序》灵感来源

序 大家好呀&#xff0c;我是summo&#xff0c;这次来写写我在上班空闲(摸鱼)的时候做的一个小网站的事。去年阿里云不是推出了个活动嘛&#xff0c;2核2G的云服务器一年只要99块钱&#xff0c;懂行的人应该知道这个价格在业界已经是非常良心了&#xff0c;虽然优惠只有一年&a…

C++初阶学习——探索STL奥秘——模拟实现string类

1、string类的构造 上面的代码从表面看没什么问题&#xff0c;但是运行后会发现程序有多处bug 但是如上图一样&#xff0c;这样改进依然有bug 因为我们编写无参构造函数的时候&#xff0c;肯定要让_str默认为nullptr&#xff0c;但是这样的话&#xff0c;在main函数中创建对象…

电脑运行库问题怎么修复?电脑运行库修复工具分享与实操

在我们日常使用电脑的过程中&#xff0c;经常会遇到一些因为运行库缺失或损坏而导致软件无法正常运行的问题。这些问题不仅影响工作效率&#xff0c;还可能导致数据丢失或程序崩溃。那么&#xff0c;电脑运行库怎么修复呢&#xff1f;本文将为您详细介绍如何使用运行库修复工具…

STL-list

1.list 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。 3. l…

黑马Java零基础视频教程精华部分_12_面向对象进阶(4)_内部类

《黑马Java零基础视频教程精华部分》系列文章目录 黑马Java零基础视频教程精华部分_1_JDK、JRE、字面量、JAVA运算符 黑马Java零基础视频教程精华部分_2_顺序结构、分支结构、循环结构 黑马Java零基础视频教程精华部分_3_无限循环、跳转控制语句、数组、方法 黑马Java零基础视…

IEEE Trans系列,超低自引率,沾边可收,截稿在即,版面有限!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解期刊最新动态&#xff01; &#x1f447; &#x1f447; &#x1f447; &#x1f447; 这本IEEE Trans系列&#xff01;指标优秀&#xff01; IEEE-Trans系列期刊IEEE TRANSACTIONS ON INTELLIGENT VEHICLES (查看原文)…

详解直铺防静电瓷砖的特点与优势

防静电地板分为架空防静电地板和直铺防静电地板&#xff0c;直铺式防静电地板是一种直接铺设在地面上的地板系统&#xff0c;防静电瓷砖就是常用的直铺防静电地板之一。防静电瓷砖是在瓷砖烧制过程中加入防静电功能粉体进行物理改性&#xff0c;规格为600*600*10mm&#xff0c;…

前端常用的几个工具网站

觉得不错的前端工具类网站 1、Grid布局生成 https://cssgrid-generator.netlify.app 2、拟物按钮样式生成 https://neumorphism.io 3、玻璃形态效果 在线制作CSS玻璃形态 4、一些Button、checkBox、switch、card的css样式 零代码 - 精美CSS样式库 5、CSS阴影生成 在线创建…

学习c语言第二十天(自定义类型)

一、结构体 1.结构体声明 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.1结构体的声明 struct stu {char name[20];int age; }s1,s2;//s1,s2是struct stu 类型的变量&#xff0c;//可以不创建&#xff0c;在main函数里创建 …

进程的管理与控制详解:创建、终止、阻塞等待与非阻塞等待

目录 一、进程创建 1、实例 2、fork函数详解 (1)fork函数模板 (2). fork() 函数的工作原理 (3). fork() 返回值和错误处理 3、如何理解进程创建过程 二、进程终止 1、终止是在做什么&#xff1f; 2、进程终止&#xff0c;有三种情况 3、进程如何终止&#xff1f; 三…

【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测

【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测 目录 【独家原创RIME-CNN-LSSVM】基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测效果一览基本介绍程序设计参考资料 效果一览 基本…

c->c++(四):gtest

本文主要探讨gtest相关内容。 gtest安装 wget -O gtest.zip https://github.com/google/googletest/archive/refs/heads/main.zipunzip gtest.zipcd googletest-mainmkdir bulid && cd buildcmake .. && make && make install gtest API TEST/TEST…

Redis02——缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、缓存工具封装)

目录 缓存概念 添加Redis缓存 业务场景 缓存作用模型 java代码 缓存更新策略 主动更新的三种策略 主动更新——Cache Aside Pattern 实际应用 缓存穿透 概念 解决方法 实际应用 缓存雪崩 概念 解决方法 缓存击穿 互斥锁 介绍 实际应用 逻辑过期 介绍 实际…

基于Yolov8面部七种表情检测与识别C++模型部署

表情识别 七种表情识别是一个多学科交叉的研究领域&#xff0c;它结合了心理学、认知科学、计算机视觉和机器学习等学科的知识和技术。 基本概念 表情的定义&#xff1a;表情是人们在情绪体验时面部肌肉活动的结果&#xff0c;是人类情感交流的基本方式之一。基本表情理论&a…

使用Step Functions运行AWS Backup时必备的权限要点

引言 在尝试从Step Functions执行AWS Backup的按需备份时&#xff0c;我在权限方面遇到了一些困难。为了备忘&#xff0c;我将这些经验写成这篇文章。 概述 从Step Functions执行AWS Backup时&#xff0c;需要分配以下权限&#xff1a; AWS Backup相关权限 执行备份的权限…