MQTT协议解析---(转)

网上已有相关讲解,对协议分析得很详细,记录学习一下备用,原blog地址见末尾。

MQTT 3

MQTT 3 (当前版本3.1.1)是目前使用的最为广泛的MQTT协议标准。尽管MQTT5标准已经发布,并且带来了一些令人振奋的新特性,但是在整个应用场景上,从后台服务到消息中间件再到客户端SDK等环节上的产品升级并没有都完成,再加上既有部署的维护,业界从版本3到5的过渡可能会持续相当长一段时间,所以,对于刚加入物联网行业的生力军来说,现在来学习MQTT 3依然是一件很有意义的事情。

MQTT协议的工作方式

在一个QMTT协议中有三个角色会参与到整个通信过程,发布者(publisher)、代理(broker)和订阅者(subscriber)。有别于传统的客户端/服务器通讯协议,MQTT协议并不是端到端的,消息传递通过代理,包括会话(session)也不是建立在发布者和订阅者之间,而是建立在端和代理之间。代理解除了发布者和订阅者之间的耦合。

除了发布者和订阅者之间传递普通消息,代理还可以为发布者处理保留消息和遗愿消息,并可以更改服务质量(QoS)等级。

MQTT控制报文

MQTT协议工作在TCP之上,端和代理之间通过交换预先定义的控制报文来完成通信。MQTT报文有3个部分组成,并按下表顺序出现:

固定报头(fixed header)可变报头(variable header)荷载(payload)
所有报文都包含 部分报文包含 部分报文包含

所有的MQTT控制报文都有一个固定报头,期格式如下:



 

协议版本3定义了14种MQTT报文,用于建立/断开连接、发布消息、订阅消息和维护连接。固定报头的第一字节的4-7位的值指定了报文类型,其取值如下表。0和15为系统保留值;0-3位为标志位,依照报文类型有不同的含义,事实上,除了PUBLISH报文以外,其他报文的标志位均为系统保留。如果收到报文的标志位无效,代理应断开连接。

报文类型描述
CONNECT 1 客户端向代理发起连接请求
CONNACK 2 连接确认
PUBLISH 3 发布消息
PUBACK 4 发布确认
PUBREC 5 发布收到(QoS2)
PUBREL 6 发布释放(QoS2)
PUBCOMP 7 发布完成(QoS2)
SUBSCRIBE 8 客户端向代理发起订阅请求
SUBACK 9 订阅确认
UNSUBSCRIBE 10 取消订阅
UNSUBACK 11 取消订阅确认
PINGREQ 12 PING请求
PINGRESP 13 PING响应
DISCONNECT 14 断开连接

固定报头的第二字节起表示报文的剩余长度。最大4个字节,每字节可以编码至127,并含有一位继续位,如继续位非0,则下一字节依然为剩余长度。由此,理论上一个控制报文最长可以到256MB。

一些报文在固定报头和荷载之间可以有一个可变报头。可变报头的内容根据报文类型不同而不同。最常见的可变报头是报文标识符(PacketIdentifier)。

一些报文可以在最后携带一个荷载。不同的报文可以无荷载,可选荷载,或必须带有荷载。

CONNECT报文

CONNECT是客户端连接到代理的第一个报文,如果在连接已经存在,代理收到该报文将会断开现有连接。

CONNECT报文的固定报头

 

CONNECT报文的可变报头

CONNECT报文的可变报头由4部分组成:

  • 协议名。协议名是UTF-8编码的大写的MQTT。
  • 协议级别。MQTT 3.1.1的协议级别为4.
  • 连接标志位。定义连接行为的参数。见下表。
  • Keep Alive。2字节,客户端和代理之间的无活动时间超过该值后,应关闭连接。如果该值置0表示客户端不要求代理启用KEEPALIVE功能。

连接标志位:

76543210
  用户名 密码 保留遗愿 遗愿QoS 遗愿QoS 遗愿 清除会话 保留(0)

清除会话标志位
这个标志位定义了如何处理会话状态。如果设置为0,客户端和代理可以恢复上一次连接时的会话状态,如果上一次连接的会话状态不存在,代理将会为客户端建立一个新的会话。如果该位设置为1,则双方将清除掉上一次连接的会话状态并建立一个新的会话。

遗愿标志位
如果遗愿标志为1,则遗愿消息会被存储在代理上,当连接关闭时,代理将发布这个消息,除非在客户端断开连接时把遗愿消息清除了。

遗愿QoS标志位
指定了遗愿消息的服务质量等级。

保留遗愿消息标志位
指定在发布遗愿消息的时候,是否把该消息作为保留消息存储在代理。

用户名标志位
如果设置为1,则用户名必须出现在荷载中,反之,用户名不允许出现在荷载中。

密码标志位
如果该位为1,则密码必须出现在荷载中;如果该位为0,则密码不允许出现在荷载中。如果用户名标志位为0,则该位必须也为0。

CONNECT报文的荷载

CONNECT报文的荷载由一个或者多个字段组成,这些字段是否出现由可变报头中的标志位决定。字段总是以长度开始。字段出现的顺序必须是:客户端标识符,遗愿主题,遗愿消息,用户名,密码。

CONNECT报文的响应

在代理在为MQTT协议开放的端口上接收到TCP连接请求并建立连接后应该会收到CONNECT报文,如果在一定时间内代理没有收到CONNECT报文,则应该关闭这个TCP连接。
在收到CONNECT报文后,代理应该检查报文格式是否符合协议标准。如果不符合协议标准,代理应关闭连接,且不发送CONNACK报文给客户端。
代理可以检查CONNECT报文的内容并执行响应的认证和鉴权。如果这些检查没有通过,代理应该向客户端发送一个带有非0返回码的CONNACK报文。

CONNACK报文

CONNACK是代理用来响应客户端CONNECT的报文。代理向客户端发送的第一个报文必须是CONNACT。CONNACK有一个固定报头,一个可变报头,但是不带有荷载。

CONNACK的固定报头

CONNACT报文只有固定报头和一个2字节的可变报头,所以它的剩余长度总是2。

CONNACK报文的可变报头

CONNACK报文的可变报头为定长2字节。第一字节的0位表示是否有会话存在。如果代理上已经有请求连接的客户端的会话,且连接请求的清除会话标识为0,则该位为1,否则该位为0。客户端可以根据这一位的值采取响应行为,比如(重新)订阅主题等。

CONNACK报文的可变报头的第二字节为返回码。如果CONNECT请求的格式正确,但是代理依然不能允许客户端连接,则返回码为一个非零值。如果连接成功,则返回0。

返回码的定义:

返回码含义
0 成功,连接请求被接受。
1 拒绝连接,不可接受的协议版本。
2 拒绝连接,不被允许的身份识别符(Client Identifier)。
3 拒绝连接,服务器不可用。
4 拒绝连接,无效的用户名和密码。
5 拒绝连接,客户端无授权。
6-255 系统保留。

客户端接受到代理的CONNACK的返回码为0,则连接建立完成,双方可以开始通信。

清除会话、保留消息和QoS的组合

清除会话、保留消息等概念,在传统的客户端/服务器方式的通信中不一定会出现,这些概念有时候不太容易理解,特别是当他们被组合起来用的时候。

下面的表格汇总了当一个客户端连接上来时,它能收到消息的各种情况。

清除会话位保留位订阅QoS发布QoS可收到的消息
Y N 0 0 N
Y N 0 1 N
Y N 1 0 N
Y N 1 1 N
N N 0 0 N
N N 0 1 N
N N 1 0 N
N N 1 1 Y,会话全部消息
Y Y 0 0 Y,最后一条消息
Y Y 0 1 Y,最后一条消息
Y Y 1 0 Y,最后一条消息
Y Y 1 1 Y,最后一条消息
N Y 0 0 Y,最后一条消息
N Y 0 1 Y,最后一条消息
N Y 1 0 Y,最后一条消息
N Y 1 1 Y,会话全部消息

原blog地址:https://www.cnblogs.com/JuliaLiu/p/11244449.html

posted @ 2021-08-11 09:52  fate_WPF  阅读(386)  评论(0编辑  收藏  举报