作者:手机用户2502886695 | 来源:互联网 | 2023-06-25 11:06
在这一课中,让我们来学习 MQTT 协议的基本概念和术语,同时也会介绍一下本课程中代码的开发环境搭建。本节课核心内容包括:
- MQTT 协议的通信模型
- MQTT Client
- MQTT Broker
- MQTT 协议数据包
1.1 MQTT 协议的通信模型
就像我们在之前提到的,MQTT 的通信是通过发布/订阅的方式来实现的,消息的发布方和订阅方通过这种方式来进行解耦,它们没有直接地连接,它们需要一个中间方。在 MQTT 里面我们称之为 Broker,用来进行消息的存储和转发。一次典型的 MQTT 消息通信流程如下所示:
- 发布方将消息发送到 Broker;
- Broker 接收到消息以后,检查下都有哪些订阅方订阅了此类消息,然后将消息发送到这些订阅方;
- 订阅方从 Broker 获取该消息。
在之后的课程里面,我们将发送方称为 Publisher,将订阅方称为 Subscriber。
1.2 MQTT Client
任何终端,嵌入式设备也好,服务器也好,只要运行了 MQTT 的库或者代码,我们都称为 MQTT 的 Client。Publisher 和 Subscriber 都属于 Client,Pushlisher 或者 Subscriber 只取决于该 Client 当前的状态——是在发布还是在订阅消息。当然,一个 Client 可以同时是 Publisher 和 Subscriber。
MQTT Client 库在很多语言中都有实现,包括 Android、Arduino、Ruby、C、C++、C#、Go、iOS、Java、Javascript,以及 .NET 等。如果你要查看相应语言的库实现,可以在这里找到。
本课程中,我们主要使用 Node.js 的 MQTT Client 库来进行演示,所以需要先安装 Node.js,然后安装 MQTT Client 的 Node.js 包:
npm install mqtt -g
1.3 MQTT Broker
如前面所讲的,Broker 负责接收 Publisher 的消息,并发送给相应的 Subscriber,它是整个 MQTT 订阅/发布的核心。在实际应用中,一个 MQTT Broker 还应该提供以下一些功能:
- 可以横向扩展,比如集群,来满足大量的 Client 接入;
- 可以扩展接入业务系统;
- 易于监控,满足高可用性。
我们在导读里面提到的阿里云、腾讯云、青云之类的云服务商提供的 MQTT 服务,其实就可以理解为他们提供了满足上述要求的 MQTT Broker。
在本课程中,我们使用一个公共的 MQTT Broker —— iot.eclipse.org 做演示,同时也会学习如何搭建一个 MQTT Broker。
1.4 MQTT 协议数据包
MQTT 协议的数据包格式非常简单,一个 MQTT 协议数据包由下面三个部分组成:
- 固定头(Fixed header):存在于所有的 MQTT 数据包中,用于表示数据包类型及对应标识,表明数据包大小;
- 可变头(Variable header):存在于部分类型的 MQTT 数据包中,具体内容由相应类型的数据包决定;
- 消息体(Payload):存在于部分 MQTT 数据包中,存储消息的具体数据。
接下来看一下固定头的格式,可变头和消息体我们将在讲解各种具体类型的 MQTT 协议数据包的时候 case by case 地讨论。
固定头格式:
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
字节 1 | MQTT 数据包类型 | MQTT 数据包 Flag, 内容由数据包类型指定 |
字节 2…… | 数据包剩余长度 |
固定头的第一个字节的高 4 位 bit 用于指定该数据包的类型,MQTT 的数据包有以下一些类型:
名称 | 值 | 方向 | 描述 |
Reserved | 0 | 不可用 | 保留位 |
CONNECT | 1 | Client 到 Broker | Client 请求连接到 Broker |
CONNACK | 2 | Broker 到 Client | 连接确认 |
PUBLISH | 3 | 双向 | 发布消息 |
PUBACK | 4 | 双向 | 发布确认 |
PUBREC | 5 | 双向 | 发布收到 |
PUBREL | 6 | 双向 | 发布释放 |
PUBCOMP | 7 | 双向 | 发布完成 |
SUBSCRIBE | 8 | Client 到 Broker | Client 请求订阅 |
SUBACK | 9 | Broker 到 Client | 订阅确认 |
UNSUBSCRIBE | 10 | Client 到 Broker | Client 请求取消订阅 |
UNSUBACK | 11 | Broker 到 Client | 取消订阅确认 |
PINGREQ | 12 | Client 到 Broker | PING 请求 |
PINGRESP | 13 | Broker 到 Client | PING 应答 |
DISCONNECT | 14 | Client 到 Broker | Client 主动中断连接 |
Reserved | 15 | 不可用 | 保留位 |
固定头的低 4 位 bit 用于指定数据包的 Flag,不同的数据包类型,其 Flag 的定义是不一样的,每种数据包对应的 Flag 如下:
数据包 | 标识位 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
CONNECT | 保留位 | 0 | 0 | 0 | 0 |
CONNACK | 保留位 | 0 | 0 | 0 | 0 |
PUBLISH | MQTT 3.1.1 使用 | DUP | QoS | QoS | RETAIN |
PUBACK | 保留位 | 0 | 0 | 0 | 0 |
PUBREC | 保留位 | 0 | 0 | 0 | 0 |
PUBREL | 保留位 | 0 | 0 | 0 | 0 |
PUBCOMP | 保留位 | 0 | 0 | 0 | 0 |
SUBSCRIBE | 保留位 | 0 | 0 | 0 | 0 |
SUBACK | 保留位 | 0 | 0 | 0 | 0 |
UNSUBSCRIBE | 保留位 | 0 | 0 | 0 | 0 |
UNSUBACK | 保留位 | 0 | 0 | 0 | 0 |
PINGREQ | 保留位 | 0 | 0 | 0 | 0 |
PINGRESP | 保留位 | 0 | 0 | 0 | 0 |
DISCONNECT | 保留位 | 0 | 0 | 0 | 0 |
注意:DUP、QOS、RETAIN 标识的使用将在后续的课程中详细讲解。
从固定头的第 2 字节开始是用于标识 MQTT 数据包长度的字段,最少一个字节,最大四个字节,每一个字节的低 7 位用于标识值,范围为 0~127。最高位的 1 位是标识位,用来说明是否有后续字节来标识长度。例如:标识为 0,代表为没有后续字节;标识为 1,代表后续还有一个字节用于标识包长度。MQTT 协议规定最多可以用四个字节来标识包长度。
所以这四个字节最多可以标识的包长度为:(0xFF, 0xFF, 0xFF, 0x7F) = 268435455 字节,约 256M,这个是 MQTT 协议中数据包的最大长度。
注意:Remain Length 的值不包含固定头的大小,包括第 1 字节和 Remain Length 字段。
1.5 小结
我们在这一课中学习了 MQTT 的通信模型,以及 Client 和 Broker 的概念,同时也学习了 MQTT 数据包的格式。接下来我们开始收发数据的第一步:从 Client 连接到 Broker。
原文:https://gitchat.csdn.net/columnTopic/5be4f7522c33167c317bebdd
By Urien 2019年5月21日 09:00:35