MQTT是一个C/S架构的发布/订阅模式的消息传输协议。
基本设计思想是轻巧、开放、简单、规范,易于实现。
这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。
MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
现在基本上在IoT环境中都是使用的MQTT协议。
订阅 Subscription
订阅包含一个主体过滤器(Topic Filter)和一个最大的服务质量(Qos)等级。订阅和单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。
主题名 Topic Name
附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。
主题过滤器 Topic Filter
订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。
会话 Session
客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。
控制报文 MQTT Control Packet
通过网络连接发送的信息数据包。类似于ICMP,MQTT规范定义了十四种不同类型的控制报文,其中一个(PUBLISH报文)用于传输应用消息。
服务器 Broker
在消息订阅模型中充当服务器的角色, 类似于送信的邮差。
Qos 消息服务质量机制
通过使用Qos机制,来保证通信的质量,也就是发送connect报文的次数时间,有以下几种情况:
QoS0: “至多1次”
消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。1次发送失败后,不再重新发送。
这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。QoS1:“至少1次”
确保信息到达,发送1次对方没有确认接收后,会重新发送,但是可能会出现多次接收的情况。QoS2:“至多一次”
确保信息到达1次且仅到达1次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到1次。
对于QoS值的确认,是基于二者客户端的的最低值,例如A 客户端使用的是QoS2,B客户端使用的是QoS1,那么服务器最后使用的就是QoS1。
MQTT协议中定义了一些方法(也被称为动作),来于表示对确定资源所进行操作。这个资源可以代表预先存在的数据或动态生成数据,这取决于服务器的实现。通常来说,资源指服务器上的文件或输出。主要方法有:
在建立连接时,首先客户端往服务器发送CONNECT连接建立报文。
规定在网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文。
在一个网络连接上,客户端只能发送一次CONNECT报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接。在这个报文中包含了遗嘱信息、keep alive等标志位。
在服务器接收到CONNECT报文后,服务端发送CONNACK报文响应从客户端收到的CONNECT报文。服务端发送给客户端的第一个报文必须是CONNACK。
如果客户端在合理的时间内没有收到服务端的CONNACK报文,客户端应该关闭网络连接。合理的时间取决于应用的类型和通信基础设施。
在CONNACK报文中,主要包含连接确认标志和返回码,但是不包含有效载荷。
具体见流程图:
在发送信息的流程中主要有几种报文:
PUBLISH – 发布消息:
PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。在信息中主要的标志位是DUP(重发标志位)、QoS(服务质量标识)、Topic Nmae(主题名)等。
有了PUBLISH报文后,就可以发送QoS为0的报文:
对于QoS为0的情况,发起方在发送PUBLIC 报文后便由Broker发送给接收方,中间不再做任何处理。
对于QoS为1的报文,还需要另外1个报文类型参与:
PUBACK –发布确认:
PUBACK报文是对QoS 1等级的PUBLISH报文的响应。
有了PUBACK报文后,就可以完成QoS为1 的报文发送。
对于QoS为1的情况,发起方在发送PUBLIC 报文后便由Broker发送给接收方,接收方收到后,会回复PUBACK报文,具体流程如图:
要实现QoS为2的信息发布,还需要另外3个报文:
PUBREC – 发布收到(QoS 2,第一步)
PUBREC报文是对QoS等级2的PUBLISH报文的响应。它是QoS 2等级协议交换的第二个报文。
PUBREL – 发布释放(QoS 2,第二步)
PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文。
PUBCOMP – 发布完成(QoS 2,第三步)
PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文。
对于QoS为2的信息发布,需要:
结束。
对于QoS为2的流程,明显多了几个步骤,因此对于该类型的信息发布有较多的流量消耗。
具体流程见图:
订阅相关报文:
SUBSCRIBE - 订阅主题
客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。
每个订阅注册客户端关心的一个或多个主题。SUBSCRIBE报文也(为每个订阅)指定了最大的QoS等级,服务端根据QoS等级发送应用消息给客户端。
其主题相关数据放在了有效载荷上,并且还包含一个主题过滤器列表。
SUBACK – 订阅确认
在接收到SUBCRIBE报文后,服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。
SUBACK报文包含一个返回码清单,允许的返回码值:
- 0x00 - 最大QoS 0
- 0x01 - 成功 – 最大QoS 1
- 0x02 - 成功 – 最大 QoS 2
- 0x80 - Failure 失败
它们指定了SUBSCRIBE请求的每个订阅被授予的最大QoS等级。
订阅完成后客户端需要传输对应的信息时,会在信息上添加上主题,添加后通过PUBLIC 发送到服务端,服务端再根据主题与订阅情况发送给对应的客户端。
基于以上两个报文,订阅的流程如下:
同样的,有了订阅流程便还有取消订阅流程,相关的有两个报文:
UNSUBSCRIBE –取消订阅
客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。
关于想要取消的订阅主题列表在有效载荷中,且规定取消订阅主题必须至少包含1个取消订阅主题。
UNSUBACK – 取消订阅确认
服务端收到UNSUBSCRIBE报文后,发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。
对于取消订阅确认报文,没有有效载荷。
流程跟订阅类似:
参考资料:
MQTT官方文档