首页 > 编程知识 正文

mqtt协议详解,物联网mqtt协议

时间:2023-05-06 05:02:57 阅读:44147 作者:1075

文章目录MQTT协议MQTT协议概述MQTT通信模型MQTT客户端功能: MQTT客户端服务器功能:消息主题和服务质量MQTT控制消息固定头可变头CONNECT消息CONNACK消息有效载荷

MQTT协议MQTT协议概述

MQTT协议的全称是messagequeuingtelemetrytransport,翻译后是消息队列遥测传输协议。 这是物联网中常用的APP应用层协议,它在TCP/IP中的APP应用层运行,并且依赖于TCP协议,因此非常可靠,并且在基于TCP协议的客户端-服务器模型中显示主题消息

MQTT通信模型MQTT协议提供一对多的消息传递,能够降低APP应用的耦合度。 用户只需编写极少量的APP应用码就可以进行一对多的消息发布和订阅。 该协议基于客户端-服务器模型,协议主要有三个id :发布者、服务器和订户,其中MQTT消息的始发者和订阅者都是客户端,服务作为中继的存在, 只要将发布者发布的消息转发给订阅该主题的所有订阅者,发布者就可以发布其权限内的所有主题,而且消息发布者可以同时成为订阅者,生产者和消费者解除结合,发布的消息同时为多个

MQTT通信模型的示意图如下。

MQTT客户端功能:向其他相关客户端发布消息。 订阅主题要求接收相关的APP应用程序消息。 取消订阅主题要求删除传入的APP应用程序消息。 从服务端结束连接。 MQTT客户端服务器功能—mqtt服务器通常称为消息代理(broker ),是一种APP应用程序或设备,通常是云服务。 例如,BTA三大巨头的一些物联网平台经常使用MQTT协议。 MQTT服务器位于消息发布者和订阅者之间,用于接收消息并将其发送给订阅者,其功能包括:

接受客户端的网络连接请求。 接受来自客户端的APP应用程序消息。 处理来自客户端的订阅/取消订阅请求。 将应用消息转发到相应的订阅客户端(包括发布者本身)。 消息的主题和服务质量是什么? MQTT服务器向每个连接的客户端(订阅者)添加标签。 此标签与服务器中的所有订阅匹配,服务器将消息转发到与标签匹配的每个客户端(订阅者)。 当然,订阅者也必须拥有订阅相应主题的权限。 例如,像阿里云一样,订阅者只能订阅同一产品下的主题,而不能跨产品订阅。 通过这些操作,信息安全和多个订阅者可以立即收到消息。主题可以有多个级别,并在各个级别之间用斜线分隔,例如/test和/test/test1/test2。

投稿人和订阅者可以使用主题名称(通常为UTF-8编码格式)发布和订阅主题。 例如,可以直接定义名为" test "的主题。 大多数MQTT服务在当前服务中没有主题,但会创建相应的主题,以便客户端可以直接在该主题中发布/订阅邮件

当每个客户端和服务器连接时,它们将成为会话。 客户端和服务器之间存在状态交互。 订阅基于会话,每个订阅都包含一个表达式,用于标识与订阅相关的一个或多个主题。 由于主题筛选器可以使用通配符,因此必须指定订阅的主题名称和质量(QoS )。 订户可以订阅多个主题,并接收来自多个发布者的消息。 同样,发布者也必须首先建立与服务器的会话,并指定要发送的主题名称和服务质量。 此外,还可以向多个不同的主题发送消息。

那么服务质量是什么呢? MQTT的服务质量提供三个级别。

QoS0)最多发送一次消息。 发送消息后,收件人不会发送响应。 发件人也不会重新发送消息。 即使收到一次信息,也有可能完全没有收到。 这种服务质量经常用于无关紧要的消息传递。 因为没有消息也没什么关系。 QoS1)消息最少发送一次(消息最少可以到达一次或多次),QoS1发布消息的可变报头中包含消息标识符,需要PUBACK消息的确认。 也就是说,接收者需要返回PUBACK响应消息。 QoS2)这是最高级别的服务质量,不能允许消息丢失和重复。 但是,使用此服务质量级别会产生额外的费用。 这个水平经常被用于支付。 因为一定有支付,而且只成功了一次,所以并不是没有付钱或者多次给钱吧。 MQTT控制消息固定报头MQTT协议在TCP协议上操作。 因为客户端和服务器是APP应用层,所以必然需要一种协议在两者之间进行通信。 随之,MQTT控制消息包含在所有MQTT控制消息中,固定报头、可变报头、净荷三个部分构成的固定报头包含在可变报头和净荷包含在部分MQTT控制消息中。

固定头占用2字节的空间,具体而言

固定报头的第一个字节分为控制消息类型(4比特)和控制消息类型的标志比特,共有14种控制类型,其中0和15预留给系统。 其他类型具体如下。

类型值指示Reserved0系统将保留一条消息,请求从CONNECT1客户端连接到服务端CONNACK2

确认PUBLISH3发布消息PUBACK4消息发布收到确认(QoS 1)PUBREC5发布收到(QoS2)PUBREL6发布释放(QoS2)PUBCOMP7消息发布完成(QoS2)SUBSCRIBE8客户端订阅请求SUBACK9订阅请求报文确认UNSUBSCRIBE10客户端取消订阅请求UNSUBACK11取消订阅报文确认PINGREQ12心跳请求PINGRESP13心跳响应DISCONNECT14客户端断开连接Reserved15系统保留

固定报头的bit0-bit3为标志位,依照报文类型有不同的含义,事实上,除了PUBLISH类型报文以外,其他报文的标志位均为系统保留,PUBLISH报文的第一字节bit3是控制报文的重复分发标志(DUP),bit1-bit2是服务质量等级,bit0是PUBLISH报文的保留标志,用于标识PUBLISH是否保留,当客户端发送一个PUBLISH消息到服务器,如果保留标识位置1,那么服务器应该保留这条消息,当一个新的订阅者订阅这个主题的时候,最后保留的主题消息应被发送到新订阅的用户。

固定报头的第二个字节开始是剩余长度字段,是用于记录剩余报文长度的,表示当前的消息剩余的字节数,包括可变报头和有效载荷区域(如果存在),但剩余长度不包括用于编码剩余长度字段本身的字节数。

剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码,而对于更大的数值则按下面的方式处理:每个字节的低7位用于编码数据长度,最高位(bit7)用于标识剩余长度字段是否有更多的字节,且按照大端模式进行编码,因此每个字节可以编码128个数值和一个延续位,剩余长度字段最crdzc拥有4个字节。

当剩余长度使用1个字节存储时,其取值范围为0(0x00)~127(0x7f)。当使用2个字节时,其取值范围为128(0x80,0x01)~16383(0Xff,0x7f)。当使用3个字节时,其取值范围为16384(0x80,0x80,0x01)~2097151(0xFF,0xFF,0x7F)。当使用4个字节时,其取值范围为2097152(0x80,0x80,0x80,0x01)~268435455(0xFF,0xFF,0xFF,0x7F)。

总的来说,MQTT报文理论上可以发送最大256M的报文,当然,这种情况是非常少的。

可变报头

可变报头并不是所有的MQTT报文都带有的(比如PINGREQ心跳请求与PINGRESP心跳响应报文就没有可变报头),只有某些报文才拥有可变报头,它在固定报头和有效负载之间,可变报头的内容会根据报文类型的不同而有所不同,但可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里,而有一些报文又没有报文标识符字段,具体见表格,报文标识符结构具体见图。

报文类型是否需要报文标识符字段CONNECT不需要CONNACK不需要PUBLISH需要(如果QoS > 0)PUBACK需要PUBREC需要PUBREL需要PUBCOMP需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要

因为对于不同的报文,可变报头是不一样的,下面就简单讲解几个报文的可变报头。

CONNECT报文

在一个会话中,客户端只能发送一次CONNECT报文,它是客户端用于请求连接服务器的报文,常称之为连接报文,如果客户端发送多次连接报文,那么服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接。

CONNECT报文的可变报头包含四个字段:协议名(Protocol Name)、协议级别(Protocol Level)、连接标志(Connect Flags)以及保持连接(Keep Alive)字段。

协议名是MQTT 的UTF-8编码的字符串,其中还包含用于记录协议名长度的两字节字段MSB与LSB。

在协议名之后的是协议级别,MQTT协议使用8位的无符号值表示协议的修订版本,对于MQTT3.1版的协议,协议级别字段的值是3(0x03),而对于MQTT3.1.1版的协议,协议级别字段的值是4(0x04)。如果服务器发现连接报文中的协议级别字段是不支持的协议级别,服务端必须给发送一个返回码为0x01(不支持的协议级别)的CONNACK响应连接报文,然后终止客户端的连接请求。

连接标志字段涉及的内容比较多,它在协议级别之后使用一个字节表示,但分成很多个标志位,具体见

bit0是MQTT保留的标志位,在连接过程中,服务器会检测连接标志的bit0是否为0,如果不为0则服务器任务这个连接报文是不合法的,会终止连接请求。

bit1是清除会话标志Clean Session,一般来说,客户端在请求连接服务器时总是将清除会话标志设置为0或1,在建立会话连接后,这个值就固定了,当然这个值的选择取决于具体的应用,如果清除会话标志设置为1,那么客户端不会收到旧的应用消息,而且在每次连接成功后都需要重新订阅相关的主题。清除会话标志设置为0的客户端在重新连接后会收到所有在它连接断开期间(其他发布者)发布的QoS1和QoS2级别的消息。因此,要确保不丢失连接断开期间的消息,需要使用QoS1或 QoS2级别,同时将清除会话标志设置为0。

bit2是遗嘱标志 Will Flag,如果该位被设置为1,表示如果客户端与服务器建立了会话,遗嘱消息(Will Message)将必须被存储在服务器中,当这个客户端断开连接的时候,遗嘱消息将被发送到订阅这个会话主题的所有订阅者,这个消息是很有用的,我们可以知道这个设备的状况,它是否已经掉线了,以备启动备用方案,当然,想要不发送遗嘱消息也是可以的,只需要让服务器端收到DISCONNECT报文时删除这个遗嘱消息即可。

bit3-bit4用于指定发布遗嘱消息时使用的服务质量等级,与其他消息的服务质量是一样的,遗嘱QoS的值可以等于0(0x00),1(0x01),2(0x02),当然,使用遗嘱消息的前提是遗嘱标志位为1。

bit5表示遗嘱保留标志位,当客户端意外断开连接时,如果 Will Retain置一,那么服务器必须将遗嘱消息当作保留消息发布,反之则无需保留。

bit6是密码标志位Password Flag,如果密码标志被设置为0,有效载荷中不能包含密码字段,反之则必须包含密码字段。

bit7是用户名标志位User Name Flag,如果用户名标志被设置为0,有效载荷中不能包含用户名字段,反之则必须包含用户名字段。

保持连接字段是一个以秒为单位的时间间隔,它使用了两个字节来记录允许客户端最大空闲时间间隔,简单来说就是,客户端必须在这段时间中与服务器进行通信,让服务器知道客户端还处于连接状态而不是断开了,当然,如果没有任何其它的控制报文可以发送,客户端也必须要发送一个PINGREQ报文,以告知服务器还是处于连接状态的。

总的来说,整个CONNECT报文可变报头的内容如下,具体见

CONNACK报文

我们再来讲解一下CONNACK报文的可变报头部分,其实有了上一个的经验,这部分对大家来说是很简单的,它是由连接确认标志字段(Connect Acknowledge Flags)与连接返回码字段 (Connect Return code)组成,各占用1个字节。

它的第1个字节是 连接确认标志字段,bit1-bit7是保留位且必须设置为0, bit0是当前会话(Session Present)标志位。

它的第2个字节是返回码字段,如果服务器收到一个CONNECT报文,但出于某些原因无法处理它,服务器会返回一个包含返回码的CONNACK报文。如果服务器返回了一个返回码字段是非0的CONNACK报文,那么它必须关闭网络连接,返回码描述具体见

返回码值描述0x00连接已被服务端接受0x01连接已拒绝,服务端不支持客户端请求的MQTT协议级别0x02连接已拒绝,服务器标识符是正确的UTF-8编码,但不允许使用0x03连接已拒绝,网络连接已建立,但MQTT服务不可用0x04连接已拒绝,用户名或密码的数据格式无效0x05连接已拒绝,客户端未被授权连接到此服务器0x06~0xFF保留未使用

提示:如果服务端收到清理会话(CleanSession)标志为1的连接,除了将CONNACK报文中的返回码设置为0之外,还必须将CONNACK报文中的当前会话设置(Session Present)标志为0。

那么总的来说,CONNACK报文的可变报头部分内容具体见

在此,就不再对MQTT报文的可变报头部分过多赘述,大家可以参考MQTT协议手册,里面有很详细的描述。

有效载荷

有效载荷也是存在与某些报文中,不同的报文有效载荷也是不一样的,比如:

CONNECT报文的有效载荷(payload)包含一个或多个以长度为前缀的字段,可变报头中的标志决定是否包含这些字段。如果包含的话,必须按这个顺序出现:客户端标识符,遗嘱主题,遗嘱消息,用户名,密码 。
SUBSCRIBE报文的有效载荷包含了一个主题过滤器列表,它们标识着客户端想要订阅的主题,每一个过滤器后面跟着一个字节,这个字节被叫做服务质量要求(Requested QoS),它给出了服务端向客户端发送应用消息所允许的最大QoS等级。

这里只是讲述了一小部分内容,关于具体的有效载荷部分也可以去看MQTT手册,此处就不再赘述。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。