.NET Core集成MQTTnet实现MQTT服务端
.NET Core集成MQTTnet实现MQTT服务端
一,什么是MQTT
二,常见的MQTT软件
MQTT官网上有很多推荐,博友们可以慢慢看,附上一篇别人的开源 MQTT Broker 对比文章https://wivwiv.com/post/best-mqtt-broker
三,MQTT通讯类型
名字 |
值 |
流向 |
描述 |
CONNECT |
1 |
C->S |
客户端请求与服务端建立连接 |
CONNACK |
2 |
S->C |
服务端确认连接建立 |
PUBLISH |
3 |
CóS |
发布消息 |
PUBACK |
4 |
CóS |
收到发布消息确认 |
PUBREC |
5 |
CóS |
发布消息收到 |
PUBREL |
6 |
CóS |
发布消息释放 |
PUBCOMP |
7 |
CóS |
发布消息完成 |
SUBSCRIBE |
8 |
C->S |
订阅请求 |
SUBACK |
9 |
S->C |
订阅确认 |
UNSUBSCRIBE |
10 |
C->S |
取消订阅 |
UNSUBACK |
11 |
S->C |
取消订阅确认 |
PING |
12 |
C->S |
客户端发送PING(连接保活)命令 |
PINGRSP |
13 |
S->C |
PING命令回复 |
DISCONNECT |
14 |
C->S |
断开连接 |
四,MQTT QoS等级
QoS(Quality of Service),服务质量。MQTT中有三种Qos:
QoS0,At most once,至多一次;
QoS1,At least once,至少一次;
QoS2,Exactly once,确保只有一次。
QoS 是消息的发送方(Sender)和接受方(Receiver)之间达成的一个协议:
l QoS0 代表,Sender 发送的一条消息,Receiver 最多能收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,也就算了;
Sender 向 Receiver 发送一个包含消息数据的 PUBLISH 包,然后不管结果如何,丢弃掉已发送的 PUBLISH 包,一条消息的发送完成。
l QoS1 代表,Sender 发送的一条消息,Receiver 至少能收到一次,也就是说 Sender 向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,
QoS 要保证消息至少到达 Sender 一次,所以有一个应答的机制。
- Sender 向 Receiver 发送一个带有消息数据的 PUBLISH 包, 并在本地保存这个 PUBLISH 包。
- Receiver 收到 PUBLISH 包以后,向 Sender 发送一个 PUBACK 数据包,PUBACK 数据包没有消息体(Payload),在可变头中(Variable header)中有一个包标识(Packet Identifier),和它收到的 PUBLISH 包中的 Packet Identifier 一致。
- Sender 收到 PUBACK 之后,根据 PUBACK 包中的 Packet Identifier 找到本地保存的 PUBLISH 包,然后丢弃掉,一次消息的发送完成。
- 如果 Sender 在一段时间内没有收到 PUBLISH 包对应的 PUBACK,它将该 PUBLISH 包的 DUP 标识设为 1(代表是重新发送的 PUBLISH 包),然后重新发送该 PUBLISH 包。重复这个流程,直到收到 PUBACK,然后执行第 3 步。
l QoS2 代表,Sender 发送的一条消息,Receiver 确保能收到而且只收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,同时保证 Receiver 不会因为消息重传而收到重复的消息。
- Sender 发送 QoS 为 2 的 PUBLISH 数据包,数据包 Packet Identifier 为 P,并在本地保存该 PUBLISH 包;
- Receiver 收到 PUBLISH 数据包以后,在本地保存 PUBLISH 包的 Packet Identifier P,并回复 Sender 一个 PUBREC 数据包,PUBREC 数据包可变头中的 Packet Identifier 为 P,没有消息体(Payload);
- 当 Sender 收到 PUBREC,它就可以安全地丢弃掉初始的 Packet Identifier 为 P 的 PUBLISH 数据包,同时保存该 PUBREC 数据包,同时回复 Receiver 一个 PUBREL 数据包,PUBREL 数据包可变头中的 Packet Identifier 为 P,没有消息体;如果 Sender 在一定时间内没有收到 PUBREC,它会把 PUBLISH 包的 DUP 标识设为 1,重新发送该 PUBLISH 数据包(Payload);
- 当 Receiver 收到 PUBREL 数据包,它可以丢弃掉保存的 PUBLISH 包的 Packet Identifier P,并回复 Sender 一个 PUBCOMP 数据包,PUBCOMP 数据包可变头中的 Packet Identifier 为 P,没有消息体(Payload);
- 当 Sender 收到 PUBCOMP 包,那么它认为数据包传输已完成,它会丢弃掉对应的 PUBREC 包。如果 Sender 在一定时间内没有收到 PUBCOMP 包,它会重新发送 PUBREL 数据包。
注:QoS 是 Sender 和 Receiver 之间达成的协议,不是 Publisher 和 Subscriber 之间达成的协议。也就是说 Publisher 发布一条 QoS1 的消息,只能保证 Broker 能至少收到一次这个消息;至于对应的 Subscriber 能否至少收到一次这个消息,还要取决于 Subscriber 在 Subscribe 的时候和 Broker 协商的 QoS 等级。
五,QoS 和会话(Session)
如果 Client 想接收离线消息,必须使用持久化的会话(Clean Session = 0)连接到 Broker,这样 Broker 才会存储 Client 在离线期间没有确认接收的 QoS 大于 1 的消息。
六,QoS降级问题
在 MQTT 协议中,从 Broker 到 Subscriber 这段消息传递的实际 QoS 等于:Publisher 发布消息时指定的 QoS 等级和 Subscriber 在订阅时与 Broker 协商的 QoS 等级,这两个 QoS 等级中的最小那一个。
七,QoS选择
- 在以下情况下你可以选择 QoS0:
- Client 和 Broker 之间的网络连接非常稳定,例如一个通过有线网络连接到 Broker 的测试用 Client;
- 可以接受丢失部分消息,比如你有一个传感器以非常短的间隔发布状态数据,所以丢一些也可以接受;
- 不需要离线消息。
- 在以下情况下你应该选择 QoS1:
- 你需要接收所有的消息,而且你的应用可以接受并处理重复的消息;
- 你无法接受 QoS2 带来的额外开销,QoS1 发送消息的速度比 QoS2 快很多。
- 在以下情况下你应该选择 QoS2:
- 你的应用必须接收到所有的消息,而且你的应用在重复的消息下无法正常工作,同时你也能接受 QoS2 带来的额外开销。
八,MQTT的retain标志位
当我们使用MQTT客户端发布消息(PUBLISH)时,如果将RETAIN标志位设置为true,那么MQTT服务器会将最近收到的一条RETAIN标志位为true的消息保存在服务器端(内存或文件)。
特别注意:MQTT服务器只会为每一个Topic保存最近收到的一条RETAIN标志位为true的消息!也就是说,如果MQTT服务器上已经为某个Topic保存了一条Retained消息,当客户端再次发布一条新的Retained消息,那么服务器上原来的那条消息会被覆盖!
每当MQTT客户端连接到MQTT服务器并订阅了某个topic,如果该topic下有Retained消息,那么MQTT服务器会立即向客户端推送该条Retained消息。
九,MQTT的will(遗愿消息)
想一下以下场景,你的设备向服务端发送了在线的消息后突然爆炸了,它还没来得及和服务端说它爆炸了就死了,这样会勿让我们以为它还在线,但其实它已经挂了。 有没有方法让客户端非正常断线后通知服务端呢? 有的,就是使用遗愿消息,
在建立与服务端的连接时约定好遗愿消息,服务端会存储这个消息,当客户端非正常断线时则会向约定好的主题发送遗愿消息,同样,它也可以设置为retian。
十,基于MQTTnet实现MQTT服务端
新建一个控制台程序
安装nuget包MQTTnet,.NET Core下安装最新版本即可
修改Program.cs,编写实现代码

下载客户端测试工具MQTTX,安装即用。
启动程序,启动MQTTX
在MQTTX种新建连接client a,键入Broker地址,端口,账号和密码,然后点击连接
新建主题订阅,订阅主题testtopic/#,#代表所有testtopic下所有的子主题都订阅
新建多一个连接client b,通过client b发布消息给client a
可看到Client a已收到消息。
文章介绍MQTT的部分引用许多人的文章,由于来源太多且我也不知道看的是否为原创,因此不细细列出来了。
文章介绍MQTT的部分引用许多人的文章,由于来源太多且我也不知道看的是否为原创,因此不细细列出来了。
文章介绍MQTT的部分引用许多人的文章,由于来源太多且我也不知道看的是否为原创,因此不细细列出来了。
__EOF__

本文链接:https://www.cnblogs.com/night-li/p/14103391.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?