1. MQTT控制包
MQTT协议是基于TCP/IP层之上的应用层协议,它是通过交换预定义的MQTT控制包来实现的。一个MQTT控制包由3个部分组成,并总是按照如下顺序排列:
固定头部(所有MQTT控制包都包含)
每个MQTT命令消息的消息头部都包含一个固定头部。固定头部的格式如下表如示:
Byte 1 包含消息类型和标志(包括DUP,QoS level和RETAIN)字段
Byte 2 包含剩余长度字段(至少1个字节,最多4个字节)
其中,消息类型共14种,如下图所示:
可变头部(部分特定控制包中包含)
某些类型的MQTT命令消息还包含了一个可变头部,它位于固定头部和有效载荷之间,不同的控制包的可变头部不同。可变头部中包含:协议名称、协议版本、连接标志、 Clean session 标志、 Will 标志、 连接用户名和密码、心跳周期、连接返回码、主题名等信息。
有效载荷(部分特定控制包中包含)
部分MQTT控制包在包的最后包含有效载荷,例如,对于PUBLISH包而言,其有效载荷为应用层消息,对于SUBSCRIBE包而言,其有效载荷内容为主题过滤器列表,SUBACK包的有效载荷包含一个返回码列表(如下图所示)
2.主题名和主题过滤器
MQTT服务器(代理)是通过MQTT订阅的主题名来分发消息的,订阅的主题可以包含特殊字符,且一个客户端可以一次订阅多个主题。
主题层次分隔符(Topic level separator)
斜线(/)是用来分隔一棵主题树里的各个层次,它提供了一个层次结构的主题空间。主题层次分隔符的引入为解决主题冲突有重要的意义。
多层次通配符
数字符号(#)即多层次通配符,用来匹配一个主题内的任意层次。
例如,如果你订阅了 finance/stock/ibm/#,则你可以收到如下主题的消息:
finance/stock/ibm
finance/stock/ibm/closingprice
finance/stock/ibm/currentprice多层次通配符可以表示0个或任意多个层次。因而,finance/# 也可以匹配finance 主题,这时, # 代表0层次。
多层次通配符只有2种用法,一是只有它自己本身,二是放在主题层次分隔符之后。因此, # 和 finance/# 都是合法的,而 finance#则是不合法的。
多层次通配符在主题树使用时必须作为最后一个字符。例如, finance/# 是合法的,而 finance/#/closingprice 是不合法的。
单层次通配符
加号(+)是用来匹配一个主题层次的通配符。
例如,finance/stock/+ 可以匹配:finance/stock/ibm 和 finance/stock/xyz 主题,但不能匹配 finance/stock/ibm/closingprice主题。同时,因为单层次通配符必须匹配一个层次,所以 finance/+ 不能匹配 finance 。
单层次通配符可以用于主题树中的任意层次,而且可以与多层次通配符配合使用。与多层次通配符的用法一样,单层次通配符要么只有它自己,要么要放在主题层次分隔符之后。因而, + 和 finance/+ 都是合法的,而 finance+ 是不合法的。
单层次分隔符即可以放在主题树的最后,也可以放在主题树的中间。例如, finance/+ 和 finance/+/ibm 都是合法的。
3.遗言机制
考虑到MQTT客户端可能因为不稳定的网络环境从MQTT服务器断开,来不及通知其他客户端自己离线的情况,MQTT协议提供了遗言机制。即在建立MQTT连接时,MQTT客户端便告诉服务器当自己离线时 ,需要将某个消息发送到某个主题。
当MQTT客户端真的从服务器断开后(1.5个心跳周期未收到客户端的心跳),服务器会自动将其遗言消息发送至预设的主题,用来通知设备离线。
4.消息服务质量
MQTT消息服务质量(QoS)可分为如下三种:
QoS 0“至多一次”,消息发布完全依赖于底层TCP/IP网络。消息有可能丢失或重复。这一级别可应用于如下情景,如环境传感器数据,丢失一次读记录无所谓,因为很快下一次读记录就会产生。
QoS 1“至少一次”,确保消息到达,但消息重复有可能发生。
QoS 2“只有一次”,确保消息到达且只到达一次。这一级别可用于如计费系统等场景,在计费系统中,消息丢失或重复可能会导致生成错误的费用。
5.MQTT服务器(broker)
参考:https://github.com/mqtt/mqtt.github.io/wiki/server-support#capabilities
6.MQTT客户端
MQTT客户端既可以作订阅者、也可以作发布者,通过订阅和发布对方的主题,能够轻松实现M2M(Machine to Machine)。
MQTT客户端调试工具推荐: