概述
MQTT特点
- "轻量级"通信协议:实现MQTT协议的开销比较小,无需太多的额外数据/文本。
- 基于TCP/IP协议:建立TCP连接后,云下设备或云平台按照MQTT协议规定的数据格式来通信。(属于应用层)
- 基于客户端——服务端模式下:云下设备????客户端、云平台????服务端
- 基于[消息发布(PUBLISH)] 或 [消息订阅(SUBSCRIBE)]模式
#请求——回答模式:假设打电话的时候,只有电话被播出并且对方的电话被接听,才能开始沟通交流。典型的同步模式。
#发布——订阅模式:假设邮件发送的过程,只有邮件编辑完成之后点击发送,就可以完成。邮件服务器会将邮件发送给对应的接收者,当接收者看到邮件提醒之后,如何时候看邮件都可以。(间接联系)
#两种模式的区别: 发布——订阅模式解耦了发布消息的客户(发布者)与订阅消息的客户(订阅者)之间的关系。发布者与订阅者之间不需要直接建立联系。
如图所示,客户端B和客户端C都向MQTT订阅了主题文章,如何客户端A向MQTT发布了一个消息,这个消息的主题参数就是文章,那么MQTT会将这个主题文章消息分发给客户端B和客户端C。因为客户端B和客户端C都订阅了文章这个主题,客户端A也可以订阅这个主题,客户端A和客户端C和客户端B都可以向MQTT发布消息,逻辑上客户端A和客户端B和客户端C是可以进行通信的。但是在网络连接上,客户端A只和MQTT服务端建立网络连接,客户端B也只和MQTT服务端建立网络连接,客户端C也只和MQTT服务端建立网络连接。这样的话,消息的发布者和订阅者她们之间网络连接就是解耦的,通过MQTT服务端将消息转发给订阅者。
MQTT协议
- 客户端Client
使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以
●发布应用消息给其它相关的客户端。
●订阅以请求接受相关的应用消息。
●取消订阅以移除接受应用消息的请求。
●从服务端断开连接。 - 服务端Server
一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端
●接受来自客户端的网络连接。
●接受客户端发布的应用消息。
●处理客户端的订阅和取消订阅请求。
●转发应用消息给符合条件的已订阅客户端
#服务端不是数据的终点而是数据的中转站
数据表示
- 二进制位
字节中的位从0到7。第7位是最高有效位,第0位是最低有效位。 - 整数数值
整数数值是16位,使用大端序(big-endian,高位字节在低位字节前面)。这意味着一个16位的字在网络上表示为最高有效字节(MSB) , 后面跟着最低有效字节(LSB) - UTF-8编码字符串
文本字段编码为UTF-8格式的字符串,UTF-8编码字符串是一个高效的Unicode字符编码格式,为了支持基于文本的通信,它对ASCII字符的编码做了优化。每个字符串都要有一个两字节的长度字段作为前缀,它给出这个字符串UTF-8编码的字节数。(MQTT编程需要计算每一个字符串的长度,并且把这个长度作为前缀添加在字符串的前面)
【注意:建议大家尽量发送标准的ASCII码值】
MQTT控制报文
- MQTT控制报文的结构
●MQTT协议通过交换预定义的MQTT控制据文来通信。MQTT控制报文由三部分组成
(1)Fixed header:固定报头,所有控制报文都包含固定报头的格式如下:
●MQTT控制报文的固定报头的高四位是用来表示MQTT控制报文的类型。也就是这里的MQTT控制报文的值。第一个字节的低四位是用于制定控制报文的类型的标志位,除了发布消息的控制报文,其他控制报文都是固定的。从第二个字节开始,它是剩余长度。(剩余长度表示当前报文剩余部分的字节数,包括可变报头和负载的数据。也就是说,我们只有知道剩余长度,我们才知道这个MQTT的报文是到哪里结束。剩余长度是不包括用于编码剩余长度字段本身的字节数。剩余长度字段是使用一个变长度编码方案。每个字节中只有第七位是用于编码数据的,每个字节最高位是用于指示是否有更多的字节。因此每个字节可以编码128个数值和一个延续位。剩余长度字段最大是四个字节)
●例子:十进制64会被编码为一个字节,数值是64,十六进制表示0x40。十进制数字321(=65+2*128)被编码为两个字节,最低有效位在前,第一个字节是65+128=193
(2)Variable header:可变报头,部分控制报文包含
(3)Payload:有效载荷,部分控制报文包含 - 控制报文的种类
【注意】:PUBREC、PUBREL、PUBCOMP三个控制报文只有在通信质量为Qos=2的消息。阿里云、百度云、腾讯云、这些云平台只支持QOS=0/QOS=1的消息,当我们使用的是阿里云、百度云、腾讯云等平台,这三个报文可先不关心。
一、CONNECT——连接服务端控制报文
1、固定报头
●CONNECT-连接服务端控制报文MQTT客户端向MQTT服务端请求连接,客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文。CONNECT报文的固定报头如下:
●固定报头的第一个字节的低四位必须用数字1来表示当前报文是CONNECT报文。第一个字节的第四位是保留位0,从第二个字节开始,是剩余长度字段,剩余长度等于可变报头的长度加上有效载荷的长度。
2、可变报头
●CONNECT报文的可变报头按下列次序包含四个字段:协议名( Protocol Name )协议级别( Protocol Level), 连接标志(Connect Flags)和保持连接( Keep Alive )
2.1协议名是MQTT。【所有的字符串前都要加上两个字节的前缀来表示字符串的长度】
2.2协议级别
●客户端用8位的无符号值表示协议的修订版本。对于3.1.1版协议,协议级别字段的值是4(0x04)。如果发现不支持的协议级别,服务端必须给发送一个返回码为0x01 ( 不支持的协议级别)的CONNACK报文响应CONNECT报文,然后断开客户端的连接。
2.3连接标志
●一个字节的连接标志,连接标志字节包含一些用于指定MQTT连接行为的参数,它还指出有效载荷中的字段是否存在。
●第0为是保留位0,第一位是清理会话标志位服务端必须验证CONNECT控制报文的保留标志位(第0位)是否为0,如果不为0必须断开客户端连接。
2.3.1清理会话
● 当MQTT客户端接入MQTT服务端时,选择是否继续之前的会话。如果不清理会话,MOTT服务端会在之前交互的基础上,继续交互。如果清理会话,MQTT服务端必须新建-个全新的会话。
● 如果清理会话(CleanSession) 标志被设置为0,服务端必须基于当前会话(使用客户端标识符识别)的状态恢复与客户端的通信。如果没有与这个客户端标识符关联的会话,服务端必须创建一个新的会话。在连接断开之后,当连接断开后,客户端和服务端必须保存会话信息当清理会话标志为0的会话连接断开之后,服务端必须将之后的QoS 1和QoS 2级别的消息保存为会话状态的一部分,如果这些消息匹配断开连接时客户端的任何订阅。
● 如果清理会话(CleanSession) 标志被设置为1,客户端和服务端必须丢弃之前的任何会话并开始一个新的会话。会话仅持续和网络连接同样长的时间。与这个会话关联的状态数据不能被任何之后的会话重用。
客户端得会话状态包括:
●已经发送给服务端,但是还没有完成确认的QoS1和QoS2级别的消息。
●已从服务端接收,但是还没有完成确认的QoS 2级别的消息。
服务端的会话状态包括:
●会话是否存在,即使会话状态的其它部分都是空。
●客户端的订阅信息。
●已经发送给客户端,但是还没有完成确认的QoS1和QoS2级别的消息。
●即将传输给客户端的QoS1和QoS2级别的消息。
●已从客户端接收,但是还没有完成确认的QoS 2级别的消息。
●可选,准备发送给客户端的QoS 0级别的消息。
2.3.2遗嘱标志
连接标志位得第2位
遣嘱标志(Will Flag)被设置为1,表示如果连接请求被接受了,遺嘱(Will Message)消息必须被存储在服务端并且与这个网络连接关联。之后网络连接关闭时,服务端必须发布这个遣嘱消息,除非服务端收到DISCONNECT报文时删除了这个遗嘱消息。
遣嘱消息发布的条件,包括但不限于:
●服务端检测到了一个I/O错误或者网络故障。
●客户端在保持连接(Keep Alive) 的时间内未能通讯。
●客户端没有先发送DISCONNECT报文直接关闭了网络连接。
●由于协议错误服务端关闭了网络连接。
如果一个设备创建了遗嘱消息得话,如果它从MQTT服务端异常断开得话,MQTT服务端就会将这个设备的遗嘱消息分发给订阅了这个遗嘱主题的其他设备。
● 如果遗嘱标志被设置为1,连接标志中的Will QoS(遗嘱消息质量等级)和Will Retain(遗嘱是否保持字段)会被服务端用到,同时有效载荷中必须包含Will Topic和Will Message字段。
● 如果遗嘱标志被设置为0,连接标车中的Will QoS和Will Retain字段必须设置为0,并且有效载荷中不能包含Will Topic(遗嘱主题)和Will Message(遗嘱消息)字段。
2.3.3遗嘱QoS Will QoS
连接标志的第4和第3位。
这两位用于指定发布遗嘱消息时使用的服务质量等级。
如果遣嘱标志被设置为0,遣嘱QoS也必须设置为0(0x00)
如果遣嘱标志被设置为1,遺嘱QoS的值可以等于0(0x00)、1(0x01)、2(0x02)。它的值不能等于3。
2.3.4遺嘱保留WillRetain
连接标志的第5位
如果遣嘱消息被发布时需要保留,需要指定这一位的值。
如果遣嘱标志被设置为0,遣嘱保留(Will Retain)标志也必须设置为0。
如果遗嘱标志被设置为1 :
如果遣嘱保留被设置为0,服务端必须将遣嘱消息当作非保留消息发布。
2.3.5用户名标志User Name Flag (百度云、阿里云支持MQTT用户名+密码]的方式接入物联网平台)
连接标志位的第7位
如果用户名(User Name)标志被设置为0,有效载荷中不能包含用户名字段。
如果用户名(User Name)标志被设置为1,有效载荷中必须包含用户名字段。
2.3.6密码标志Password Flag
连接标志的第6位
如果密码(Password) 标志被设置为0,有效载荷中不能包含密码字段。
如果用户名标志被设置为0,密码标志也必须设置为0 。
2.4保持连接Keep Alive
保持连接字节如下图所示:
● 保持连接(Keep Alive)是一个以秒为单位的时间间隔,表示为一个16位的字,它是指在客户端传输完成一个控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的控制报文可以发送,客户端必须发送一个PINGREQ报文。
● 不管保持连接的值是多少,客户端任何时候都可以发送PINGREQ报文,并且使用PINGRESP报文判断网络和服务端的活动状态。
● 如果保持连接的值非零,并且服务端在1.5倍的保持连接时间内没有收到客户端的控制报文,它必须断开客户端的网络连接,认为网络连接已断开。
● 客户端发送了PINGREQ报文之后,如果在合理的时间内仍没有收到PINGRESP报文,它应该关闭到服务端的网络连接。
● 保持连接得值为零表示关闭保持连接功能。这意味着,服务端不需要因为客户端不活跃而断开连接。注意:不管保持连接得值是多少,任何时候,只要服务端认为客户是不活跃或无响应得,可以断开客户端的连接。
2.5可变报头非规范示例
(这个表格我也看不太懂,我的理解就是这个表格是之前我所描述的一些报文的一个总结,巴上面我写的所有内容概括性的汇总到了一个表格上,大家看看理解一下就好)
3、有效载荷Payload
CONNECT报文的有效载荷包含一个或多个以长度为前缀的字符串,可变报头中的标志决定是否包含这些字段。如果包含这些字段。如果出现必须按这个顺序出现:客户端标识符,遣嘱主题,遺嘱消息,用户名,密码。
3.1客户端标识符Client Identifier
● 服务端使用客户端标识符(Clientld) 识别客户端。连接服务端的每个客户端都有唯一的客户端标识符(Clientld)。客户端和服务端都必须使用Clientld识别两者之间的MQTT会话相关的状态。
● 客户端标识符(Clientld)必须存在而且必须是CONNECT报文有效载荷的第一个字段
● 客户端标识符必须是UTF-8编码字符串。
● 服务端必须允许1到23个字节长的UTF-8编码的客户端标识符,客户端标识符只能包含这些字符“01234567 89abcdefahiklmnoparstuwxvzABCDEFGHIJKLMNOPQRSTUVWXYZ" (大写字母,小写字母和数字)
● 服务端可以允许编码后超过23个字节的客户端标识符(Clientld)。服务端可以允许包含不是上面列表字符的客户端标识符。
● 服务端可以允许客户端提供一个零字节的客户端标识符(Clientld),如果这样做了, 服务端必须将这看作特殊情况并分配唯一的客户端标识符给那个客户端。然后它必须假设客户端提供了那个唯一的客户端标识符,正常处理这个CONNECT报文。
● 如果客户端提供了一个零字节的客户端标识符,它必须同时将清理会话标志设置为1.
● 如果客户端提供的Clientld为零字节且清理会话标志为0,服务端必须发送返回码为0x02示标识符不合格)的CONNACK报文响应客户端的CONNECT报文,然后关闭网络连接。
● 如果服务端拒绝了这个Clientld,它必须发送返回码为0x02 ( 表示标识符不合格)的CONNACK报文响应客户端的CONNECT报文,然后关闭网络连接
3.2遗嘱主题
如果遗嘱标志被设置为1,有效载荷的下一个字段是遗嘱主题(Will Topic)● 遺嘱主题必须是UTF-8编码字符串。
3.3遗嘱消息
● 如果遗嘱标志被设置为1,有效载荷的下一个字段是遗嘱消息。遺嘱消息定义了将被发布到遗嘱主题的应用消息。这个字段由一个两字节的长度和遗嘱消息的有效载荷组成,表示为零字节或多个字节序列。长度给出了跟在后面的数据的字节数,不包含长度字段本身占用的两个字节。
● 遗嘱消息被发布到遗嘱主题时,它的有效载荷只包含这个字段的数据部分,不包含开头的两个长度字节。
3.4用户名
如果用户名标志被设置为1,有效载荷的下一个字段就是它。用户名必须是UTF-8编码字符串。服务端可以将它用于身份验证和授权。
3.5密码
● 如果密码标志被设置为1,有效载荷的下一个字段就是密码字段。密码字段包含一个两字节的长度字段,长度表示二进制数据的字节数(不包含长度字段本身占用的两个字节,后面跟着0到65535字节的二进制数据。
● 密码字节:
【注意】可变报头和有效载荷都介绍之后,现在我们就可以把有效载荷的长度与可变报头的长度相加得出剩余长度,剩余长度最后赋值。
二、CONNACK——确认连接请求
●当服务端接收到客户端发来的请求连接报文时,客户端会向服务端响应确认请求连接报文,服务端发送给客户端的第一个报文也必须是确认连接请求报文。如果客户端在合理的时间内没有收到服务端的CONNACK报文,客户端应该关闭网络连接。合理的时间取决于应用的类型和通信基础设施。
1、固定报头
固定报头的第一个字节的高四位必须是数字2来表示当前的报文类型。低四位是保留位0,剩余长度是固定数值2.
2、可变报头
2.1连接确认标志
●第一个字节是连接确认标志,第0位是当前会话标志位,如果服务端收到清理会话(CleanSession) 标志为1的连接,除了将CONNACK报文中的返回码设置为0之外,还必须将CONNACK报文中的当前会话设置标志为0。
●如果服务端收到一个CleanSession为0的连接,当前会话标志的值取决于服务端是否已经保存了Clientld对应客户端的会话状态。如果服务端已经保存了会话状态,它必颁将CONNACK报文中的当前会话标志设置为1。如果服务端没有已保存的会话状态,它必须将CONNACK报文中的当前会话设置为0。还需要将CONNACK报文中的返回码设置为0 。
2.2连接返回码
可变报头的第二个字节是连接返回码。用来表示客户端向服务端发起的这个连接,服务端是否接接受,如果不接受,拒绝的原因是什么。如果服务端接接受的话,返回0X00表示服务端已接受连接。
【注意】确认连接请求报文没有有效载荷。
三、PUBLISH——发布消息
当我们的设备成功和MQTT建立连接之后,他们就可以通过PUBLISH发布消息控制报文发布消息。PUBLISH控制报文是指从客户端向服务端或者是服务端向客户端传输一个应用消息。
1、固定报头
固定报头的第一个字节的高四位必须是数值3。
1.1重发标志DUP
●固定报头的第一个字节的第三位
● 如果DUP标志被设置为0,表示这最客户端或服务端第一次请求发送这个PUBLISH报文。如果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。
● 客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1
● 对于QoS 0的消息,DUP标志必须设置为0
● 服务端发送PUBLISH报文给订阅者时,收到(入站)的PUBLISH报文的DUP标志的值不会被传播。发送(出站)的PUBLISH报文与收到( 入站)的PUBLISH报 文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定。
1.2服务质量等级QoS
固定报头的第一个字节的第2-1位
这个应用消息的服务质量等级是多少,需不需要接收方发送应答。
1.3保留标志RETAIN
● 固定报文的第一个字节的第0位
● 问候消息:客户端发布的RETAIN=1的消息,服务端保留为问候消息当新客户订阅相应主题时,服务端将消息发送给订阅者。
● 如果客户端发给服务端的PUBLISH报文的保留(RETAIN) 标志被设置为1,服务端必须存储这个应用消息和它的服务质量等级(QoS), 以便它可以被分发给未来的主题名匹配的订阅者。一个新的订阅建立时,对每个匹配的主题名, 如果存在最近保留的消息,它必须被发送给这个订阅者。 如果服务端收到一条保留(RETAIN) 标志为1的QoS 0消息,它必须丢弃之前为那个主题保留的任何消息。它应该将这个新的QoS 0消息当作那个主题的新保留消息,但是任何时候都可以选择丢弃它,如果这种情况发生了,那个主题将没有保留消息。
● 服务端发送PUBLISH报文给客户端时,如果消息是作为客户端一个新订阅的结果发送,它必须将报文的保留标志设为1。当一个PUBLISH报文发送给客户端是因为匹配一个已建立的订阅时,服务端必须将保留标志设为0,不管它收到的这个消息中保留标志的值是多少。
2、可变报头
2.1主题名
● 第一个字段必须是主题名,主题名用于识别有效载荷数据应该被发布到哪一个信息通道。
● 假设,客户端B订阅了一个主题W,客户端C也订阅了一个主题X,如果我们客户端A发布了一个消息,这个消息的主题是W,那么MQTT服务端接收到这个主题之后会根据这个主题W来将这个消息分发给客户端B而不会分发给客户端C。
● PUBLISH报文中的主题名不能包含通配符。
2.2报文标识符
● 只有当QoS等级是1或2时,报文标识符字段才能出现在PUBLISH报文中。
● PUBLISH报文非规范示例:
●PUBLISH报文可变报头非规范示例:
2.3有效载荷
●有效载荷包含将被发布的应用消息,数据的内容和格式是应用特定的(纯文本字符串、JSON字符串)。有效载荷的长度计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷PUBLISH报文是合法的。
2.4响应
●PUBLISH报文的接收者必须根据PUBLISH报文中的QoS等级发送响应
2.5动作
● 客户端使用PUBLISH报文发送应用消息给服务端,目的是分发到其他订阅匹配的客户端。服务端使用PUBLISH报文发送应用消息给每一个订阅匹配的客户端。
四、PUBACK——发布确认
PUBACK报文是对QoS 1等级的PUBLISH报文的响应。(确认报文没有有效载荷)
1、固定报头
固定报头的第一个字节的高四位必须是数值4,来保证这个报文是发布确认报文。第四位是保留位,剩余长度是固定数值2
2、可变报头
等待确认的PUBLISH报文的报文标识符。
五、SUBSCRIBE——订阅主题
客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅注册客户端关心的一个或多个主题。为了将应用消息转发给与那些订阅匹配的主题,服务端发送PUBLISH报文给客户端。SUBSCRIBE报文也( 为每个订阅)指定了最大的QoS等级,服务端根据这个发送应用消息给客户端。
1、固定报头
固定报头的高四位必须是数值8,低四位是0010,剩余长度等于可变报头的长度加上有效载荷的长度。
2、可变报头
2.1报文标识符
● 很多控制报文的可变报头部分包含一个两字节的报文标识符字段。这些报文是PUBLISH (QoS> 0时),PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCIBE,UNSUBACK。
● SUBSCRIBE,UNSUBSCRIBE和PUBLISH (QoS大于0)控制报文必须包含一个非零的16位报文标识符客户端每次发送一个新的这些类型的报文时都必须分配一个当前未使用的报文标识符。如果一个客户端要重发这个特殊的控制报文,在随后重发那个报文时,它必须使用相同的标识符。当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1的PUBLISH对应的是PUBACK,QoS 2的PUBLISH对应的是PUBCOMP,与SUBSCRIBE或UNSUBSCRIBE对应的分别是SUBACK或UNSUBACK 。发送一个QoS 0的PUBLISH报文时, 相同的条件也适用于服务端。
● QoS等于0的PUBLISH报文不能包含报文标识符。
● PUBACK, PUBREC, PUBREL报文必须包含与最初发送的PUBLISH报文相同的报文标识符。类似地,SUBACK和UNSUBACK必须包含对应的SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符。
2.2有效载荷
● SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们表示客户端想要订阅的主题。SUBSCRIBE报文有效载荷中的主题过滤器列表必须是UTF-8字符串。服务端应该支持包含通配符(4.7.1节定义的)的主题过滤器。如果服务端选择不支持包含通配符的主题过滤器,必须拒绝任何包含通配符过滤器的订阅请求。每一个过滤器后面跟着一个字节,这个字节被叫做服务质量要求,它给出了服务端向客户端发送应用消息所允许的最大QoS等级。订阅Oos的作用:允许服务端向客户端分发消息的质量等级。订阅QoS的作用就是允许服务端向客户端分发消息的质量等级。
● SUBSCRIBE报文的有效载荷必须包含至少一对主题过滤器和QoS等级字段组合。没有有效载荷的SUBSCRIBE报文是违反协议的。
● 请求的最大服务质量等级字段编码为一个字节,它后面跟着UTF-8编码的主题名,那些主题过滤器1和QoS等级组合是连续地打包。
● SUBSCRIBE报文有效载荷格式
● 有效载荷非规范示例:
● 有效载荷字节格式非规范示例:
六、SUBACK——订阅确定
当服务端接收到客户端发送的订阅主题报文时,服务端会返回订阅确定报文给客户端,用于确定它已收到并正在处理SUBSCRIBE报文。
1、固定报头
固定报头的第一个字节高四位是9,低四位是0,剩余长度等于可变报头的长度加上有效载荷长度。
2、可变报头
可变报头包含等待确定的SUBSCRIBE报文的报文标识符
SUBACK报文可变报头:
3、有效载荷
有效载荷包含一个返回码清单,每个返回码对应等待确定的SUBSCRIBE报文中的一个主题过滤器。返回码的顺序必须和SUBSCRIBE报文中主题过滤器的顺序相同。
SUBACK报文有效载荷格式:
返回0x00——最大QoS1
返回0x01——成功-最大QoS2
返回0x02——成功-最大QoS2
返回0x80——Failure失败
0x00 0x01 0x02 0x80之外的SUBACK返回码是保留的,不能使用。
有效载荷非规范示例:
有效载荷字节格式非规范示例:
七、UNSUBSCRIBE——取消订阅
客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题
1、固定报头
固定报头的第一个字节的高四位必须是10来确定报文类型,保留位0010,剩余长度等于可变报头的长度加有效载荷的长度。
2、可变报头
可变报头包含一个报文标识符。
3、有效载荷
● UNWUBSCRIBE报文的有效载荷包含客户端想着取消主题过滤器列表。
● UNWUBSCRIBE报文中的主题过滤器必须至少包含一个消息过滤器,没有有效载荷的UNSUBSCRIBE报文是违反协议的。
● 有效载荷字节格式非规范示例:
八、UNSUBACK——取消订阅确认
服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文
1、固定报头
固定报头的第一个字节的高四位位11,保留位为0 ,剩余长度为固定值2
2、可变报头
可变报头包含等待确认的取消订阅报文的报文标识符。
3、有效载荷
没有有效载荷
九、PINGREQ——心跳请求
客户端发送PINGREQ报文给服务端的。用于:
1.在没有任何其它控制报文从客户端发给服务的时,告知服务端客户端还活着。
2.请求服务端发送响应确认它还活着。
3.使用网络以确认网络连接没有断开。
保持连接(Keep Alive)处理中用到这个报文。为了保持我们的设备与服务端的连接,我们需要定时向服务端发送心跳请求报文。定时时长尽量不能大于我们保持连接的时长。
1、固定报头
2、可变报头
PINGREQ报文没有可变报头
3、有效载荷
PINGREQ报文没有有效载荷
十、PINGRESP——心跳响应
当服务端接收到客户端发送的心跳请求时,服务端会向客户端响应心跳响应报文。表示服务端还活着。
1、固定报头
2、可变报头
PINGRESP报文没有可变报头
3、有效载荷
PINGRESP报文没有有效载荷
十一、DISCONNECT——断开连接
我们的客户端可以主动向服务端发送断开连接报文,表示客户端正常断开。
1、固定报头
服务端必须验证所有的保留位都被设置为0,如果它们不为0必须断开连接。
2、可变报头
DISCONNECT报文没有可变报头
3、有效载荷
DISCONNECT报文没有有效载荷
4、响应
客户端发送DISCONNECT报文之后:
●必须关闭网绮连接
●不能通过那个网络连接再发送任何控制报文
服务端在收到DISCONNECT报文时:
●必须丢弃任何与当前连接关联的未发布的遗嘱消息
●应该关闭网络连接,如果客户端没有断开网络连接。
MQTT相关注意事项
- MQTT协议要求基础传输层可以提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)的字节流。所有要使用TCP/IP协议
- MQTT允许主题过滤器中使用通配符,但是主题名不可以使用通配符。
- MQTT允许使用以“ ” 开 头 的 主 题 , 但 是 服 务 端 不 可 以 将 “ ”开头的主题,但是服务端不可以将“ ”开头的主题,但是服务端不可以将“"字符开头的主题名匹配通配符(#/+)开头的主题过滤器,服务端应该阻止客户端使用这种主题名与其他客户端交换消息。
- 主题名和主题过滤器是区分大小写的。
- MQTT协议规定了大部分通信的规则,但是还有一部分通信规则没有规定,交由MQTT服务端(云平台来规定)比如:用户名/密码的位数、发布消息的有效载荷格式(纯文本/JSON/。。。)客户端订阅的最大主题数量。
通配符
1、主题通配符
主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层级。
订阅的主题过滤器可以包含特殊的通配符,允许你一次订阅多个主题。
主题过滤器中可以使用通配符,但是主题名不能使用通配符。
2、主题层级分隔符
斜杠“/”用于分割主题的每个层级,为主题名提供一个分层结构。当客户端订阅指定的主题过滤器包含两种通配符时,主题层级分隔符就很有用了。主题层级分隔符可以出现。在主题过滤器或主题名字的任何位置,相邻的主题层次分隔符表示一个零长度的主题层级。
3、多层通配符
数字标志“#"是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须位于它自己的层级或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符。
4、单层通配符
加号“+”是只能用于单个主题层级匹配的通配符。在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。然而它必须占据过滤器的整个层级。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用。
服务质量等级和协议流程QoS
MQTT按照这里定义的服务质量(QoS)等级分发应用消息。分发协议是对称的,在下面的描述中,客户端和服务端既可以是发送者也可以是接收者。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。
#【MQTT客户端】>【MQTT服务端】发布消息
#【MQTT服务端】>【MQTT客户端】分发消息
(1)QoS 0:最多分发一次
消息分发依赖于底层网络的能力,接收者不会发送响应,发送者也不会重试。消息可能送达一次也可能根本没有发送。
(2)QoS 1:至少发送一次
服务质量确保消息至少送达一次。QoS 1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK报文确定。发送方发送了这个消息之后,它需要等待接收方的应答,如果接收方没有应答,那么发送方会再次发送这个消息,那么这个消息就至少发送了一次。
(3)QoS 2:仅分发一次(了解)
这是最高等级的服务质量,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。使用之前所说的PUBREC、PUBREL、PUBCOMP三个控制报文来实现之分发一次。百度云、阿里云、腾讯云、支持QoS=0/QoS=1,不支持QoS-2。
【注意】发布消息QoS:客户端发布消息到服务端时,此消息的服务质量,是需要应答还是不需要应答。订阅主题QoS:服务端分发消息到客户端时,此消息的服务质量,是需要应答还是不需要应答。这两个QoS互不相关。
**【注意】**即使我写了这么多关于MQTT协议的内容,但是单看协议内容是不足已明白这个协议的其中的道理的,以为这个协议又长又难,所以建议大家先通过客户端来和MQTT服务端进行交互,对照着MQTT协议,加深对MQTT协议的理解。这样会事半功倍。
参考连接
https://www.bilibili.com/video/BV1dJ411S723?p=48
最后
以上就是会撒娇小松鼠为你收集整理的学习日记——MQTT协议初学的全部内容,希望文章能够帮你解决学习日记——MQTT协议初学所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复