MQTTnet 3.0.5学习笔记
段时间在使用MQTTnet,都说这个东西比较好,可是翻了翻网上没有例子给参考一下。
今天算是找到了,给高手的帖子做个宣传吧.
原网址如下:https://blog.csdn.net/chenlu5201314/article/details/94740765
由于GitHub上介绍的东西比较少,以我的水平真是不知道怎么用,先照葫芦画瓢,再看看怎么回事吧:
功能:
把订阅与发布做成一个类,还带有自动重连的功能
using System.Threading;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client; //客户端需要用到
using MQTTnet.Client.Options; //具体连接时需要用到的属性,ID的名称,要连接Server的名称,接入时用到的账号和密码,掉线时是否重新清除原有名称,还有许多...
using MQTTnet.Packets; //这个没用上
using MQTTnet.Protocol; //这个也没用上
using MQTTnet.Client.Receiving; //接收
using MQTTnet.Client.Disconnecting; //断线
using MQTTnet.Client.Connecting; //连接
新建一个类:先写一下变量和一些字段
class HOSMQTT
{
private static MqttClient mqttClient = null;
private static IMqttClientOptions options = null;
private static bool runState = false;
private static bool running = false;
/// <summary>
/// 服务器IP
/// </summary>
private static string ServerUrl = "182.61.51.85";
/// <summary>
/// 服务器端口
/// </summary>
private static int Port = ;
/// <summary>
/// 选项 - 开启登录 - 密码
/// </summary>
private static string Password = "ruichi8888";
/// <summary>
/// 选项 - 开启登录 - 用户名
/// </summary>
private static string UserId = "admin";
/// <summary>
/// 主题
/// <para>China/Hunan/Yiyang/Nanxian</para>
/// <para>Hotel/Room01/Tv</para>
/// <para>Hospital/Dept01/Room001/Bed001</para>
/// <para>Hospital/#</para>
/// </summary>
private static string Topic = "China/Hunan/Yiyang/Nanxian";
/// <summary>
/// 保留
/// </summary>
private static bool Retained = false;
/// <summary>
/// 服务质量
/// <para>0 - 至多一次</para>
/// <para>1 - 至少一次</para>
/// <para>2 - 刚好一次</para>
/// </summary>
private static int QualityOfServiceLevel = ;
}
先看一下Start方法
public static void Start()
{
try
{
runState = true;
Thread thread = new Thread(Work); //原帖中是这样写的 Thread thread = new Thread(new ThreadStart( Work));
thread.IsBackground = true;
thread.Start();
}
catch (Exception ex)
{
Console.WriteLine( "启动客户端出现问题:" + ex.ToString());
}
}
没进入正题之前,先普及一下基本知识
C#的ThreadStart 和 Thread多线程,new Thread(t1);和new Thread(new ThreadStart(t1));没有什么区别.前者是.net的写法,后者是C#的写法
具体请看下面的连接
https://www.cnblogs.com/rosesmall/p/8358348.html
进入整体,介绍连接方法 Work
private static void Work()
{
running = true;
Console.WriteLine("Work >>Begin");
try
{
var factory = new MqttFactory(); //声明一个MQTT客户端的标准步骤 的第一步
mqttClient = factory.CreateMqttClient() as MqttClient; //factory.CreateMqttClient()实际是一个接口类型(IMqttClient),这里是把他的类型变了一下
options = new MqttClientOptionsBuilder() //实例化一个MqttClientOptionsBulider
.WithTcpServer(ServerUrl, Port)
.WithCredentials(UserId, Password)
.WithClientId("XMan")
.Build();
mqttClient.ConnectAsync(options); //连接服务器
//下面这些东西是什么,为什么要这么写,直到刚才我还是不懂,不过在GitHub的网址我发现了出处.
mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(new Func<MqttClientConnectedEventArgs, Task>(Connected));
mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(new Func<MqttClientDisconnectedEventArgs, Task>(Disconnected));
mqttClient.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(new Action<MqttApplicationMessageReceivedEventArgs>(MqttApplicationMessageReceived));
while (runState)
{ Thread.Sleep(); }
}
catch(Exception exp)
{ Console.WriteLine(exp);
}
Console.WriteLine("Work >>End"); running = false; runState = false;
}
先来看看MqttClient 类里面都有什么东西

需要实现的接口,如何实现,说重点!
在GitHub上有个地方进去看看就知道了‘

这个页面的最下方写着如何实现 https://github.com/chkr1011/MQTTnet/wiki/Upgrading-guide
private void Something()
{
mqttClient.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(OnAppMessage);
mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnConnected);
mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnDisconnected);
} private async void OnAppMessage(MqttApplicationMessageReceivedEventArgs e)
{
} private async void OnConnected(MqttClientConnectedEventArgs e)
{
} private async void OnDisconnected(MqttClientDisconnectedEventArgs e)
{
}
在开始Connected方法之前有必要看一下关于同步和异步的知识,
现学现卖简单说一下:
Task就是异步的调用,就在不影响主线程运行的另一个线程,但是他能像线程池一样更高效的利用现有的空闲线程
async必须用来修饰Task ,void,或者Task<TResult>, await是等待异步线程Task.Run()开始的后台线程执行完毕。
记住要是Task 实现异步功能,必须用 async 修饰,且async 与await成对出现。
详见下面大神写的大作:https://www.cnblogs.com/doforfuture/p/6293926.html
下面是什么意思?
mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(new Func<MqttClientConnectedEventArgs, Task>(Connected));
MqttClientConnectedHandlerDelegate 这个实例实现了mqttClient.ConnectedHandler接口
new Func<MqttClientConnectedEventArgs, Task>(Connected) ,
使用Func委托传入MqttClientConnectedEventArgs类型的参数,返回的类型是Task,Task是一个类,这个类没有返回值,如果有返回值就是Task<TResult>。
是委托就要带一个方法取实现,这个方法就是Connected。
这句话的意思是,用MqttClientConnectedHandlerDelegate实现接口,同时使用委托取调用Connected的方法,并且给这个方法传入一个MqttClientConnectedEventArgs参数,
这个委托的返回值是Task(就是不需要返回类型的异步调用),这也就定义了Connected的类型必须是async Task。
好了来看下 Connected,这个函数什么意思
就是与服务器连接之后要干什么,订阅一个Topic,或几个Topic。连接之前已经连接了Connectasync(),如果断线还会重连,后面会提到。
这个就连接之后需要做的事----订阅!
private static async Task Connected(MqttClientConnectedEventArgs e)
{
try
{
List<TopicFilter> listTopic = new List<TopicFilter>();
if (listTopic.Count() <= )
{
var topicFilterBulder = new TopicFilterBuilder().WithTopic(Topic).Build();
listTopic.Add(topicFilterBulder);
Console.WriteLine("Connected >>Subscribe " + Topic);
} await mqttClient.SubscribeAsync(listTopic.ToArray());
Console.WriteLine("Connected >>Subscribe Success");
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
}
TopicFilter是一个Topic详细信息的类

掉线的发生时会执行这个函数
private static async Task Disconnected(MqttClientDisconnectedEventArgs e)
{
try
{
Console.WriteLine("Disconnected >>Disconnected Server");
await Task.Delay(TimeSpan.FromSeconds());
try
{
await mqttClient.ConnectAsync(options);
}
catch (Exception exp)
{
Console.WriteLine("Disconnected >>Exception " + exp.Message);
}
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
}
越写问题越多,这个为什么断线的时候会执行这个方法,这不是事件,只是接口!
怎么实现的?看了一下源码,一时只看了大概,这些功能的绑定都是在ConnectAsync的时候就完成了!
下面接收到消息的时候
/// <summary>
/// 接收消息触发事件
/// </summary>
/// <param name="e"></param>
private static void MqttApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
{
try
{
string text = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
string Topic = e.ApplicationMessage.Topic; string QoS = e.ApplicationMessage.QualityOfServiceLevel.ToString();
string Retained = e.ApplicationMessage.Retain.ToString();
Console.WriteLine("MessageReceived >>Topic:" + Topic + "; QoS: " + QoS + "; Retained: " + Retained + ";");
Console.WriteLine("MessageReceived >>Msg: " + text);
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
}
}
最后就是发布:一般会选择0,如果选择其他的情况在订阅端不在的时候,服务器可能会崩溃
/// <summary>
/// /// 发布
/// <paramref name="QoS"/>
/// <para>0 - 最多一次</para>
/// <para>1 - 至少一次</para>
/// <para>2 - 仅一次</para>
/// </summary>
/// <param name="Topic">发布主题</param>
/// <param name="Message">发布内容</param>
/// <returns></returns>
public static void Publish( string Topic,string Message)
{
try
{
if (mqttClient == null)
return;
if (mqttClient.IsConnected == false)
mqttClient.ConnectAsync(options);
if (mqttClient.IsConnected == false)
{
Console.WriteLine("Publish >>Connected Failed! ");
return;
}
Console.WriteLine("Publish >>Topic: " + Topic + "; QoS: " + QualityOfServiceLevel + "; Retained: " + Retained + ";");
Console.WriteLine("Publish >>Message: " + Message);
MqttApplicationMessageBuilder mamb = new MqttApplicationMessageBuilder()
.WithTopic(Topic)
.WithPayload(Message).WithRetainFlag(Retained);
if (QualityOfServiceLevel == )
{
mamb = mamb.WithAtMostOnceQoS();
}
else if (QualityOfServiceLevel == )
{
mamb = mamb.WithAtLeastOnceQoS();
}
else if (QualityOfServiceLevel == )
{
mamb = mamb.WithExactlyOnceQoS();
}
mqttClient.PublishAsync(mamb.Build());
}
catch (Exception exp)
{
Console.WriteLine("Publish >>" + exp.Message);
}
}
重点补充一下:
这两天验证的时候发现,对于MQTT服务器来说客户端的用户名必须是唯一的,
举例:同一台电脑上,两个程序同时发布(publish)到一个MQTT服务器,必须设置两个不同的ClientId,否则只有一个能连接上。
Paho的使用:
具体说明也可以看这位高手的:
https://blog.csdn.net/weixin_42133779/article/details/80226633
只是有一点需要强调以下:
Paho的目录不要太深,之前我就是三层文件夹下面,结果无法运行。一直提示 error code=13
没办法把他放在D盘的根目录下就可以了
纸上得来终觉浅,要改造成自己想要的些东西,还要花些功夫!不过这已经很好了!谢谢各位高手的贡献
MQTTnet 3.0.5学习笔记的更多相关文章
- 从零开始搭建.NET Core 2.0 API(学习笔记一)
从零开始搭建.NET Core 2.0 API(学习笔记一) 一. VS 2017 新建一个项目 选择ASP.NET Core Web应用程序,再选择Web API,选择ASP.NET Core 2. ...
- Swift 2.0 字符串学习笔记(建议掌握OC字符串知识的翻阅)
自己公司开现在使用OC语言在写,但Swift似乎是苹果更推荐使用的开发语言,估计也是未来开发的趋势,自己以前有接触swift,但又由于公司的项目赶,也没有时间去好好地学习这款开发语言.现在年底了,项目 ...
- Spring 4.0.2 学习笔记(2) - 自动注入及properties文件的使用
接上一篇继续, 学习了基本的注入使用后,可能有人会跟我一样觉得有点不爽,Programmer的每个Field,至少要有一个setter,这样spring配置文件中才能用<property> ...
- Spring 4.0.2 学习笔记(1) - 最基本的注入
1. 添加maven支持 <dependency> <groupId>org.springframework</groupId> <artifactId> ...
- Google Guava14.0 瓜娃学习笔记
Guava 是java api的增强与扩展,提供复杂的java 数据结构,使你的代码更简短精炼,具有良好的可读性.看看guava给我们提供了哪些很酷的功能: 集合创建: Map<String, ...
- 《Ruby语言入门教程v1.0》学习笔记-01
<Ruby语言入门教程v1.0> 编著:张开川 邮箱:kaichuan_zhang@126.com 想要学习ruby是因为公司的自动化测试使用到了ruby语言,但是公司关于ruby只给了一 ...
- Swift2.0 函数学习笔记
最近又有点忙,忙着找工作,忙着适应这个新环境.现在好了,上班两周周了,也适应过来了,又有时间安安静静的就行我们前面的学习了.今天这篇笔记,记录的就是函数的使用.下面这些代码基本上是理清楚了函数的额使用 ...
- Vue1.0基础学习笔记整理
最近一直在使用Vue.js开发项目,现将在学习过程中遇到的一些学习小细节总结如下: 1.只处理单次插值,今后的数据变化就不会再引起插值更新了 <span>This will never c ...
- vue2.0 路由学习笔记
昨天温故了一下vue2.0的路由 做个笔记简单记录一下! 1.首相和vue1.0一样 要使用vuejs的路由功能需要先引入vue-router.js 2.然后修改原有a标签处代码 这里以一个ul li ...
随机推荐
- IDEA新建本地项目关联远程git仓库
现在远程git仓库创建一个repository,然后本地创建项目,最后进行关联.三板斧,打完收工. 第一步.第二步地球人都知道,略过不表,第三步比较关键,举个例子: 0.创建本地Git仓库:VCS - ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_19-微服务之间认证-Feign 拦截器
4.2 Feign 拦截器 4.2.1 定义Feign拦截器 微服务之间使用feign进行远程调用,采用feign拦截器实现远程调用携带JWT. 在common工程添加依赖: <dependen ...
- 测试理论03-svn-缺陷及报告-jira
回顾--用例设计方法 边界值(三个点,使用步骤) 判定表(适用,四个组成部分,规则,使用) 因果图(适用,四个符号,使用) 正交表(定义,特性,L_n(m^k),因素,水平,使用,工具allpairs ...
- Elasticsearch 7.x文档基本操作(CRUD)
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html 1.添加文档 1.1.指定文档ID PUT ...
- 代理IP爬取和验证(快代理&西刺代理)
前言 仅仅伪装网页agent是不够的,你还需要一点新东西 今天主要讲解两个比较知名的国内免费IP代理网站:西刺代理&快代理,我们主要的目标是爬取其免费的高匿代理,这些IP有两大特点:免费,不稳 ...
- 【Leetcode_easy】671. Second Minimum Node In a Binary Tree
problem 671. Second Minimum Node In a Binary Tree 参考 1. Leetcode_easy_671. Second Minimum Node In a ...
- 01.轮播图之二 :tableView 轮播
在做这个tablevew轮播的时候,重要的就是修改frame 和view 的翻转了:::: 也是不难的,概要的设计和scroll 轮播是一致的: 首先是 .h 的文件 @interface Table ...
- maven:手动上传jar私服
转:https://www.jianshu.com/p/b8ec688c388e 打包时提示私服中找不到以下jar包 在私服中搜索确实找不到,后来知道这些是老系统的jar包没有deploy到私服 经分 ...
- 项目中常用的19条MySQL优化技巧
原文:https://segmentfault.com/a/1190000012155267 声明一下:下面的优化方案都是基于 “ Mysql-索引-BTree类型 ” 的 一.EXPLAIN 做My ...
- 修改NGUI 3.11 的控件 inputfileld hide input 属性bug
1.勾选hideinput属性后,输入中文,会出现,无法显示的问题. 2.勾选hideinput属性后,密码框会出现第一个字母被吃掉的问题 解决方案:控件都不要勾选hideinput属性,代码做如下修 ...