MQTT学习:协议介绍

什么是MQTT

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

协议解析

MQTT协议由三部分组成:

  • 固定报头(Fixed header)
  • 可变报头(Variable header)
  • 有效载荷(Payload)

固定报头

每个MQTT控制报文都包含一个固定报头(长度为2~5个bytes)
图示

Bit76543210
byte1MQTT控制报文的类型用于指定控制报文类型的标志位
byte2 剩余长度
  • MQTT控制报文的类型
    位于固定报头的第一个字节高四位,详细值代表类型如下表
名字报文流动方向描述
Reserved0禁止保留
CONNECT1客户端到服务端客户端请求连接服务端
CONNACK2服务端到客户端连接报文确认
PUBLISH3两个方向都允许发布消息
PUBACK4两个方向都允许QoS 1消息发布收到确认
PUBREC5两个方向都允许发布收到(保证交付第一步)
PUBREL6两个方向都允许发布释放(保证交付第二步)
PUBCOMP7两个方向都允许QoS 2消息发布完成(保证交互第三步)
SUBSCRIBE8客户端到服务端客户端订阅请求
SUBACK9服务端到客户端订阅请求报文确认
UNSUBSCRIBE10客户端到服务端客户端取消订阅请求
UNSUBACK11服务端到客户端取消订阅报文确认
PINGREQ12客户端到服务端心跳请求
PINGRESP13服务端到客户端心跳响应
DISCONNECT14客户端到服务端客户端断开连接
Reserved15禁止保留
  • 用于指定控制报文类型的标志位
    该标志位表示MQTT报文类型特定的标值,此处只要关注PUBLISH报文的标志位。
  1. Bit3是DUP位,重复分发。在QoS质量>0的情况下,PUBLISH、PUBREL报文在一定时间内,没有收到客户端的回复,则需要重发该消息,置该标志位为1,且保证报文标识符相同。(下面说明什么是报文标识符)
  2. Bit2 & Bit1 是QoS位,即消息服务质量等级。
  3. Bit0是保留信息位,如果该位置为1,则MQTT Broker会把该次报文的信息保留下来,如有新客户端订阅,Broker会下发该保留信息。
  • 剩余长度
    表示当前报文剩余部分的字节数,包括可变报头和负载的数据。

可变报头

  • 报文标识符
    主要作用是在客户端与服务端信息传递时消息的唯一验证,在重复消息的情况下能保证消息的准确性。
Bit7 - 0
byte 1报文标识符 MSB
byte 2报文标识符 LSB

需要注意以下几点:

  1. SUBSCRIBE,UNSUBSCRIBE和PUBLISH(QoS大于0)控制报文必须设置报文标识符(以下称为packetId)
  2. 客户端发送新的消息时必须分配一个当前未使用的packetId
  3. 重发消息时,packetId保持一致
  4. QoS=0的PUBLISH报文不能包含packetId
  5. PUBACK, PUBREC, PUBREL报文必须包含与最初发送的PUBLISH报文相同的packetId 。类似地,SUBACK和UNSUBACK必须包含在对应的SUBSCRIBE和UNSUBSCRIBE报文中使用的packetId。
  • 其他
    不同的报文类型有不同的可变报头,具体的说明可以看下面控制报文一章

有效载荷

有效载荷就是我们传递的主要消息体。

控制报文

下面来简述下MQTT的控制报文类型,可参考MQTT协议中文版

CONNECT

当客户端与服务端(以下称为Broker)网络连接成功后,客户端会给Broker发送CONNECT报文。
我们主要根据可变报头的连接标志位来解析有效载荷(Payload)

  • 遗嘱
    顾名思义,客户端在非正常的与Broker断开通信时,Broker会发送遗嘱消息。
    包括但不限于以下条件:
  1. 服务端检测到了一个I/O错误或者网络故障。

  2. 客户端在保持连接(Keep Alive)的时间内未能通讯。

  3. 客户端没有先发送DISCONNECT报文直接关闭了网络连接。

  4. 由于协议错误服务端关闭了网络连接。

    当Will Flag为1时,该客户端需要Broker保存遗嘱信息。
    遗嘱信息主要包含有效消息、主题、Qos。Broker还需要根据Will Retain来判断是否需要保留遗嘱信息。

  • 用户名和密码
    用来校验客户端是否能连接Broker

  • 客户端标识符 Client Identifier
    客户端的唯一标识,连接Broker时必须要带上此参数,否则Broker会拒绝连接。

  • 清除会话 Clean Session
    客户端连接Broker时会带上Clean Session参数,该参数作用就是决定本次连接是否要恢复上一次连接的相关会话信息。
    当CleanSession 为1时,Broker应把该客户端(客户端标识符作为一标识)上一次连接会话的相关数据删除,包括客户端的订阅信息、没有完成的QoS1或QoS2的消息(包括PUBLISH、PUBREL报文)、即将传输的QoS1或QoS2的消息。
    当CleanSession为0时,本次连接应基于上一次该客户端会话相关数据来创建会话,恢复包括订阅信息,重发没有完成的QoS1或QoS2的消息(包括PUBLISH、PUBREL报文),重发即将传输的QoS1或QoS2的消息。

CONNACK

Broker收到客户端的CONNECT报文后,经过一系列处理,会返回去CONNACK报文。
包含以下返回码:

返回码响应描述
00x00连接已接受连接已被服务端接受
10x01连接已拒绝,不支持的协议版本服务端不支持客户端请求的MQTT协议级别
20x02连接已拒绝,不合格的客户端标识符客户端标识符是正确的UTF-8编码,但服务端不允许使用
30x03连接已拒绝,服务端不可用网络连接已建立,但MQTT服务不可用
40x04连接已拒绝,无效的用户名或密码用户名或密码的数据格式无效
50x05连接已拒绝,未授权客户端未被授权连接到此服务器

PUBLISH

PUBLISH的重发(DUP)还有保留(RETAIN)就不重复描述了,在这里主要介绍下服务质量QoS。

QoS值Bit 2Bit 1描述
000最多分发一次
101至少分发一次
210只分发一次
  • QoS0
    此等级的消息,发布者只会发送一次,不管订阅者是否能收到消息
  • QoS1
    此等级的消息,会确保订阅者至少收到一次,发布者会一直尝试发送PUBLISH,直到它收到PUBACK才会停止
  • QoS2
    此等级的消息,会确保订阅者只收到一次。

下面贴张网上找的图片,帮助大家熟悉不同消息质量的交互(图片来源:https://www.jianshu.com/p/8b0291e8ee02)。

在这里插入图片描述
在这里插入图片描述
初学者可能会对Broker在数据交互过程中的定位会有疑问,下一章我会写到基于Netty开发的MQTT Broker,希望能帮助到大家。

PUBACK

当QoS = 1时,收到来自发布者消息的订阅者会返回PUBACK报文,响应发布者已收到消息,至此,QoS = 1的消息交互结束。

PUBREC

当QoS = 2时,订阅者收到PUBLISH报文后,会返回PUBREC报文。

PUBREL

当QoS = 2时,发布者收到订阅者返回的PUBREC报文后,会发送PUBREL报文到订阅者。

PUBCOMP

当QoS = 2时,订阅者收到发布者发送的PUBREL报文后,会返回PUBCOMP报文到订阅者。至此,QoS = 2的消息交互结束。

大家可以借助上图来理解

SUBSCRIBE

订阅报文必须包含有效载荷,且至少要有一对主题过滤器和QoS等级字段组合。
若保留消息中存在匹配该主题的消息,Broker应发送该保留信息到刚订阅的客户端。
主题过滤器支持通配符#和+两种符号

  • +,单层通配符,支持匹配一层主题。
    例如,topicFilter为 /hello/+/world,则符合的有下面这些情况/hello/a/world、/hello/b/world、/hello/c/world…但像/hello/a/b/world这种情况就不能匹配了。
  • #,多层匹配符,支持匹配多层主题。
    例如,topicFilter为 /hello/#,则符合的有下面这些情况/hello/a/world、/hello/b/world、/hello/a/b/world、/hello/a/b/c/world、/hello

需要注意,多层匹配符一定要在主题的最后

SUBACK

订阅确认,类似于连接确认,按顺序返回主题过滤器的QoS质量值集合。

UNSUBSCRIBE

取消订阅,必须包含有效载荷,且至少要有一对主题过滤器和QoS等级字段组合。
Broker在删除该订阅时,

  • 它必须停止分发任何新消息给这个客户端 。
  • 它必须完成分发任何已经开始往客户端发送的QoS 1和QoS 2的消息。
  • 它可以继续发送任何现存的准备分发给客户端的缓存消息。

UNSUBACK

确认订阅取消报文

PINGREQ

客户端发送PINGREQ报文给Broker的。用于:

  • 在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
  • 请求服务端发送 响应确认它还活着。
  • 使用网络以确认网络连接没有断开。

PINGRESP

Broker发送PINGRESP报文响应客户端的PINGREQ报文。表示还存活。

DISCONNECT

断开连接报文,Broker收到客户端的DISCONNECT报文后,应

  • 删除遗嘱消息
  • 关闭网络连接

总结

本篇文章主要是介绍MQTT协议的部分知识点,结合了MQTT协议官方文档和自己的理解,方便自己学习,也希望能帮助到感兴趣的伙伴,如有不明白或有问题的地方欢迎指出。计划下一篇会写基于Netty开发的MQTT Broker,欢迎关注。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

碩果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值