文章目录
- 一、啥是MQTT?
- 1. MQTT协议特点
- 2. 发布和订阅
- 3. QoS(Quality of Service levels)
- QoS 0 —— 最多1次
- QoS 1 —— 最少1次
- QoS 2 —— 只有1次
- 二、MQTT 数据包结构
- 1. MQTT固定头
- 2. MQTT可变头 / Variable header
- 3. Payload消息体
- 三、MQTT 消息报文
一、啥是MQTT?
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。
MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。
作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
1. MQTT协议特点
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。
MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。
其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
MQTT协议除标准版外,还有一个简化版MQTT-SN,该协议主要针对嵌入式设备,这些设备一般工作于TCP/IP网络,如:ZigBee。
MQTT 与 HTTP 一样,MQTT 运行在传输控制协议/互联网协议 (TCP/IP) 堆栈之上。
结构示意图:
2. 发布和订阅
MQTT使用的发布/订阅消息模式,它提供了一对多的消息分发机制,从而实现与应用程序的解耦。
这是一种消息传递模式,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的。
MQTT 服务器是发布-订阅架构的核心。
它可以非常简单地在Raspberry Pi或NAS等单板计算机上实现,当然也可以在大型机或 Internet 服务器上实现。
服务器分发消息,因此必须是发布者,但绝不是订阅者!
客户端可以发布消息(发送方)、订阅消息(接收方)或两者兼而有之。
客户端(也称为节点)是一种智能设备,如微控制器或具有 TCP/IP 堆栈和实现 MQTT 协议的软件的计算机。
消息在允许过滤的主题下发布。主题是分层划分的 UTF-8 字符串。不同的主题级别用斜杠/作为分隔符号。
我们来看看下面的设置。
- 光伏发电站是发布者(Publisher)。
- 主要主题(Topic)级别是"PV",这个工厂发布两个子级别"sunshine"和"data";
- "PV/sunshine"是一个布尔值(true/fault,也可以是 1/0),充电站需要它来知道是否应该装载电动汽车(仅在阳光普照时 😃)。
- 充电站(EVSE)是订阅者,订阅"PV/sunshine"从服务器获取信息。
- “PV/data” 另一方面,以 kW 为单位传输工厂产生的瞬时功率,并且该主题可以例如通过计算机或平板电脑订阅,以生成一天内传输功率的图表。
这就是一个简单的MQTT的应用场景,具体如下图所示;
3. QoS(Quality of Service levels)
服务质量是 MQTT 的一个重要特性。当我们使用 TCP/IP 时,连接已经在一定程度上受到保护。但是在无线网络中,中断和干扰很频繁,MQTT 在这里帮助避免信息丢失及其服务质量水平。这些级别在发布时使用。如果客户端发布到 MQTT 服务器,则客户端将是发送者,MQTT 服务器将是接收者。当MQTT服务器向客户端发布消息时,服务器是发送者,客户端是接收者。
QoS 0 —— 最多1次
最小的等级就是 0。并且它保证一次信息尽力交付。一个消息不会被接收端应答,也不会被发送者存储并再发送。这个也被叫做 “即发即弃” 。并且在TCP协议下也是会有相同的担保。
QoS 1 —— 最少1次
当使用QoS 等级1 时, 它保证信息将会被至少发送一次给接受者。 但是消息也可能被发送两次甚至更多 。
QoS 2 —— 只有1次
最高的QoS就是2,它会确保每个消息都只被接收到的一次,他是最安全也是最慢的服务等级。
二、MQTT 数据包结构
- 固定头(Fixed header),存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识;
- 可变头(Variable header),存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容;
- 消息体(Payload),存在于部分MQTT数据包中,表示客户端收到的具体内容;
整体MQTT的消息格式如下图所示;
1. MQTT固定头
固定头存在于所有MQTT数据包中,其结构如下:
固定头存在于所有MQTT数据包中, 固定头包含两部分内容,首字节(字节1)和剩余消息报文长度(从第二个字 节开始,长度为1-4字节),剩余长度是当前包中剩余内容长度的字节数,包括变量头和有效负载中的数据)。剩余长度不包含用来编码剩余长度的字节。
剩余长度使用了一种可变长度的结构来编码,这种结构使用单一字节表示0 - 127 的值。大于 127 的值如下处 理。每个字节的低7 位用来编码数据,最高位用来表示是否还有后续字节。因此每个字节可以编码 128 个值,再加 上一个标识位。剩余长度最多可以用四个字节来表示。
2. MQTT可变头 / Variable header
可变标头组件作为可选字段包含在某些 MQTT 控制数据包类型中。在固定报头和有效载荷之间是这个字段。可变标头的内容由数据包类型决定。在可变报头中可以找到许多数据包类型中常见的数据包标识符字段。数据包标识符字段是一个 2 字节整数,包含在许多 MQTT 控制数据包类型的可变标头组件中。
数据包标识符字段如下:
PUBLISH、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK
数据包标识符字段的特征:
-
如果 QoS(服务质量)的值设置为零,则 PUBLISH 数据包不应包含数据包标识符字段。这意味着如果 QoS 值大于零,则数据包标识符字段将仅出现在 PUBLISH 数据包中。
-
客户端在发送新的 SUBSCRIBE、UNSUBSCRIBE 或 PUBLISH MQTT 控制数据包时应分配一个当前未使用的非零数据包标识符。
-
服务器在发送新的 PUBLISH MQTT 控制数据包时应分配一个当前未使用的非零数据包标识符。
-
PUBACK、PUBREC、PUBUREL、PUBREC是PUBLISH命令确认包,包标识符与PUBLISH包相同
-
SUBACK和UNSUBACK分别是SUBSCRIBE和UNSUBSCRIBE确认包。
-
SUBACK 和 UNSUBACK 数据包与 SUBSCRIBE 和 UNSUBSCRIBE 数据包共享相同的数据包标识符处理完相应的确认包后,包标识符可以重复使用。
下面是一个定义:
A。如果 QoS 设置为 1,则 PUBLISH 的确认包将是 PUBACK。如果处理了 PUBACK,则可以重用 PUBACK 数据包标识符。
B.如果 QoS 值为 2,则 PUBLISH 确认包将是 PUBCOMP 或 PUBREC。
3. Payload消息体
Payload消息体是MQTT数据包的第三部分,CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息 有消息体:
CONNECT
,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码SUBSCRIBE
,消息体内容是一系列的要订阅的主题以及QoS。SUBACK
,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。UNSUBSCRIBE
,消息体内容是要订阅的主题。
三、MQTT 消息报文
以上介绍了MQTT协议的消息格式,MQTT消息格式包含Fixed Header, Variable Header和Payload。因为MQTT消息格式非常精简,所以可以高效的传输数据。
Fixed Header中包含首字节,高4位用来表示报文类型,低4位用于类型控制。目前只有PUBLISH使用了类型控制字段。其它控制字段被保留并且必须与协议定义保持一致。
Fixed Header同时包含Remaining Length,这是剩余消息长度,最大长度为4字节,理论上一条MQTT最大可以传输256MB数据。Remaining Length=Variable Header+Payload长度。
Variable Header是可变头部,有些报文类型中需要包含可变头部,可变头部根据报文类型不同而不同。比如Packet Identifier在发布,订阅/取消订阅等报文中都使用到。
Payload是消息内容,也只在某些报文类型中出现,其内容和格式也根据报文类型不同而不同。