MQTT协议
MQTT是什么
MQTT是可以让两个设备之间实现网络通讯的一种传输协议。可以实现像智能家居——从手机上可以实时查看家里各设备(冰箱,空调,电饭煲,扫地机器人等等)的状态,并且可以进行远程控制。
接下来将会以网上购物【发送、接收】快递进行举例说明
MQTT是一客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IOT)
MQTT工作原理
MQTT主要由MQTT服务端、 MQTT客户端、MQTT主题组成
MQTT服务端
专门接收客户端发送过来的消息,并针对客户端发送的信息必要性进行保存(不是所有消息都要保存)以提升mqtt传输的稳定性
相当于快递柜专门用来存放快递
MOTT服务端通常是一台服务器。它是MOTT信息传输的枢纽,负责将MOTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。
MQTT客户端
通过服务端建立通信的双方,可以向服务端发送信息,也可以从服务端接受信息
相当于用户和快递小哥。快递小哥把我们的快递放在快递柜里,我们去快递柜里取出我们的快递;我们也可以将我们要寄的快递放在快递柜里,然后快递小哥给我们寄出去
MOTT客户端可以向服务端发布信息,也可以从服务端收取信息。我们把客户端发送信息的行为成为
“发布”
信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅”
信息。“订阅”信息这一操作很像我们在视频网站订阅某一部电视剧。当这部电视剧上新后,视频网站会向订阅了该剧的用户发送信息,告诉他们有新剧上线了。
MQTT主题
客户端在向服务端发送信息的时候会携带一个主题字段,用以辨别信息种类。当其他客户端在订阅的时候就可以根据主题进行区分,从而准确的订阅自己需要的信息。
相当于我们取快递时候的取件码一样
刚刚我们在讲解MQTT客户端订阅信息时,使用了用户在视频网站订阅电视剧这个例子。在MQTT通讯中,客户端所订阅的肯定不是一部部电视剧,而是一个个“主题”。MOTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。
MQTT使用案例
信息查看
- 汽车将其速度信息发布到服务器上,服务器将该汽车的速度信息转发到订阅了该汽车速度主题的客户端上。从而实现我们在手机和电脑上实时监控汽车速度的需求。
控制操作
- 我们使用手机或者电脑将降低空调温度这一指令的消息发送到服务器上,服务器根据主题订阅将信息发送给汽车客户端。从而实现了远程控制的需求
MQTT 发布/订阅 特性
MQTT通讯的核心枢纽是MQTT服务端。有了服务端对MQTT信息的接收、储存、处理和发送,客户端在发布和订阅信息时,可以相互独立,且在空间上可以分时间上可以异步。
- 相互独立
发送者客户端和订阅者客户端是相互独立互不相干的,发送者客户端向服务器发送信息是不会受订阅者客户端干扰的,不管该主题的消息有多少订阅者订阅或者是没有订阅者订阅发送者都不会受其影响。相反,订阅者客户端不管有没有发送者发送该主题也不会受其影响
- 空间分离
客户端和客户端之间是不受空间限制的,拿上述汽车的例子来说明。即使汽车在东北,手机在上海,电脑在深圳,也可以实现上述信息查看、控制操作的需求,只要网路畅通。
- 时间异步
客户端和客户端之间的发布订阅不一定要在同一时刻完成。比如,手机像汽车发送命令的时候,汽车正好驶入山洞里,山洞里没有网络,等汽车驶出山洞网络恢复,再接收到手机的命令并进行操作。这样也是可以的
连接MQTT 服务端
CONNECT – 连接服务端
首先MQTT客户端将会向服务端发送连接请求。该请求实际上是一个包含有连接请求信息的数据包。这个数据包的官方名称为CONNECT。
MQTT客户端要想连接服务端,首先要向服务端发送CONNECT报文。如果此CONNECT报文的格式或内容不符合MQTT规范,则服务器会拒绝客户端的连接请求。
名称 | 解释 |
---|---|
clientId | 客户端ID |
cleanSession | 清除会话 |
keepAlive | 心跳时间间隔 |
- clientId (客户端ID)
ClientId是MQTT客户端的标识。MQTT服务端用该标识来识别客户端。因此ClientId必须是独立的。如果两个MQTT客户端使用相同ClientId标识,服务端会把它们当成同一个客户端来处理。通常ClientId是由一串字符所构成的,如上图所示,此示例中的clientID是“client-1”。
- cleanSession(清除会话)
如果cleanSession 被设置为“true”。那么服务端不需要客户端确认收到报文,也不会保存任何报文。
如果我们将cleanSession 设置为”false”。那么服务端就知道,后续通讯中,客户端可能会要求我保存没有收到的报文。
- keepAlive (心跳时间间隔)
MQTT服务端运行过程中,当有客户端因为某种原因断开了与服务端的连接,服务端需要实时了解这一情况。KeepAlive(心跳时间间隔)正是用于服务端了解客户端连接情况的。
CONNACK – 确认连接请求
MQTT服务端收到客户端连接请求后,会向客户端发送连接确认。同样的,该确认也是一个数据包。这个数据包官方名称为CONNACK
名称 | 解释 |
---|---|
returnCode | 连接返回码 |
sessionPresent | 当前会话 |
- returnCode(连接返回码)
当服务端收到了客户端的连接请求后,会向客户端发送returnCode(连接返回码),用以说明连接情况。如果客户端与服务端成功连接,则返回数字“0”。如果未能成功连接,连接返回码将会是一个非零的数值,具体这个数值的含义,请见下表:
返回码 | 返回码描述 |
---|---|
0 | 成功连接 |
1 | 连接被服务端拒绝,原因是不支持客户端的MQTT协议版本 |
2 | 连接被服务端拒绝,原因是不支持客户端标识符的编码。可能造成此原因的是客户端标识符编码是UTF-8,但是服务端不允许使用此编码。 |
3 | 连接被服务端拒绝,原因是服务端不可用。即,网络连接已经建立,但MQTT服务不可用。 |
4 | 连接被服务端拒绝,原因是用户名或密码无效。 |
5 | 连接被服务端拒绝,原因是客户端未被授权连接到此服务端。 |
- sessionPresent (当前会话)
首先,当客户端发送的CONNECT报文中的cleanSession设置为true。在这种情况下,客户端是不需要服务端保存任何报文的。那么服务端发送的确认连接CONNACK报文中,sessionPresent肯定是false,也就是说,服务端没有保存任何报文。
当客户端发送的CONNECT报文中的cleanSession设置为false时,客户端是要求服务端保存报文的。在这种情况下,如果服务端的确保存了没有收到客户端接收确认的报文信息,那么cleanSession为true,否则为false。
发布、订阅和取消订阅
PUBLISH – 发布信息
MQTT客户端一旦连接到服务端,便可以发布消息。 每条发布的MQTT消息必须包含一个主题。MQTT服务器可以通过主题确定将消息转发给哪些客户端。(注:这里的消息指的是MQTT报文。)
名称 | 解释 |
---|---|
topicName | 主题名 |
QoS | 服务质量等级 |
packetId | 报文标识符 |
retainFlag | 保留标志 |
Payload | 有效载荷 |
dupFlag | 重发标志 |
- topicName – 主题名
主题名用于识别此信息应发布到哪一个主题
- QoS – 服务质量等级
QoS(Quality of Service)表示MQTT消息的服务质量等级。QoS有三个级别:0、1和2。QoS决定MQTT通讯有什么样的服务保证。
- packetId – 报文标识符
报文标识符可用于对MQTT报文进行标识。不同的MQTT报文所拥有的标识符不同。MQTT设备可以通过该标识符对MQTT报文进行甄别和管理。请注意:报文标识符的内容与QoS级别有密不可分的关系。只有QoS级别大于0时,报文标识符才是非零数值。如果QoS等于0,报文标识符为0。
- retainFlag – 保留标志
在默认情况下,当客户端订阅了某一主题后,并不会马上接收到该主题的信息。只有在客户端订阅该主题后,服务端接收到该主题的新信息时,服务端才会将最新接收到的该主题信息推送给客户端。
但是在有些情况下,我们需要客户端在订阅了某一主题后马上接收到一条该主题的信息。这时候就需要用到保留标志这一信息。关于保留标志的具体使用方法,我们将在本教程的后续部分进行详细讲解。
- Payload – 有效载荷
有效載荷是我们希望通过MQTT所发送的实际内容。我们可以使用MQTT协议发送文本,图像等格式的内容。这些内容都是通过有效载荷所发送的。
- dupFlag – 重发标志
当MQTT报文的接收方没有及时确认收到报文时,发送方会重复发送MQTT报文。在重复发送MQTT报文时,发送方会将此“重发标志”设置为true。请注意,重发标志只在QoS级别大于0时使用。
SUBSCRIBE – 订阅主题
- 客户端要想订阅主题,首先要向服务端发送主题订阅请求。客户端是通过向服务端发送SUBSCRIBE报文来实现这一请求的。该报文包含有一系列“订阅主题名”。请留意,一个SUBSCRIBE报文可以包含有单个或者多个订阅主题名。也就是说,一个SUBSCRIBE报文可以用于订阅一个或者多个主题。
- 客户端在订阅主题时也可以明确QoS。服务端会根据SUBSCRIBE中的QoS来提供相应的服务保证。
- 另外每一个SUBSCRIBE报文还包含有“报文标识符”。报文标识符可用于对MQTT报文进行标识。不同的MQTT报文所拥有的标识符不同。MQTT设备可以通过该标识符对MQTT报文进行甄别和管理。
SUBACK – 订阅确认
服务端接收到客户端的订阅报文后,会向客户端发送SUBACK报文确认订阅。
SUBACK报文包含有“订阅返回码”和“报文标识符”这两个信息。
订阅返回码
名称 | 解释 |
---|---|
返回码 | Return Code Response |
0 | 订阅成功 – QoS 0 |
1 | 订阅成功- QoS 1 |
2 | 订阅成功- QoS 2 |
128 | 订阅失败 |
UNSUBSCRIBE – 取消订阅
当客户端要取消订阅某主题时,可通过向服务端发送UNSUBSCRIBE –
取消订阅报文来实现。UNSUBSCRIBE报文包含两个重要信息,第一个是取消订阅的主题名称。同一个UNSUBSCRIBE报文可以同时包含多个取消订阅的主题名称。另外,UNSUBSCRIBE报文也包含“报文标识符”,MQTT设备可以通过该标识符对报文进行管理。