【MQTT】MQTT协议学习

MQTT协议

简述

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。


特点

本协议运行在TCP/IP,或其它提供了有序、可靠、双向连接的网络连接上。它有以下特点:

  • 使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。
  • 消息传输不需要知道负载内容。
  • 提供三种等级的服务质量。
  • 很小的传输消耗和协议数据交换,最大限度减少网络流量。
  • 异常连接断开发生时,能通知到相关各方。

MQTT消息的QoS(服务质量)

MQTT支持三种QoS等级:

QoS 0 : “最多一次”,尽操作环境所能提供的最大努力分发消息。分发的消息可能丢失或重复。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久后还会有第二次发送。

QoS 1 :“至少一次”,确保消息可以到达,但消息可能会重复。

QoS 2 :“只有一次”,确保消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。


协议实现方式

实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。

客户端 Client
使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以

  • 打开连接到服务端的网络连接
  • 发布应用消息给其它相关的客户端
  • 订阅以请求接受相关的应用消息
  • 取消订阅以移除接受应用消息的请求
  • 关闭连接到服务端的网络连接

服务端 Server
一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端

  • 接受来自客户端的网络连接
  • 接受客户端发布的应用消息
  • 处理客户端的订阅和取消订阅请求
  • 转发应用消息给符合条件的已订阅客户端
  • 关闭来自客户端的网络连接

应用消息

MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:

  • Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload);
  • payload,可以理解为消息的内容,是指订阅者具体要使用的内容。

MQTT协议数据包(控制报文)结构

在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、可变头(Variable header)、消息体(payload)三部分构成。MQTT数据包结构如下:

  • (1)固定头(Fixed header)。存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识。
  • (2)可变头(Variable header)。存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容。
  • (3)消息体(Payload)。存在于部分MQTT数据包中,表示客户端收到的具体内容。
MQTT固定头

固定头存在于所有MQTT数据包中,其结构如下:

比特位7 6 5 43 2 1 0
byte 1MQTT控制报文的类型用于指定控制报文类型的标志位
byte 2剩余长度
MQTT数据包类型

位置:Byte 1中bits 7-4。

相于一个4位的无符号值,类型、取值及描述如下:

MQTT的消息类型

类型            值      报文流动方向             描述
CONNECT	        1	     C ->S		  	客户端请求与服务端建立连接
CONNACK	        2	     S ->C		  	服务端确认连接建立
PUBLISH	        3	     C<->S	 	 	发布消息
PUBACK	        4	     C<->S		 	收到发布消息确认
PUBREC	        5	     C<->S	 	 	发布消息收到
PUBREL	        6	     C<->S		  	发布消息释放
PUBCOMP	        7	     C<->S		  	发布消息完成
SUBSCRIBE	    8	     C ->S	 	 	订阅请求
SUBACK	        9	     S ->C		  	订阅确认
UNSUBSCRIBE	   10	     C ->S		  	取消订阅
UNSUBACK	   11	     S ->C		  	取消订阅确认
PINGEQ	       12	     C ->S	 	 	客户端发送PING(连接保活)命令
PINGRSP	       13	     S ->C		  	PING命令回复
DISCONNECT	   14	     C ->S	  		断开连接

详解:

  1. CONNECT连接服务端

    客户端到服务端的网络连接建立后, 客户端发送给服务端的第一个报文必须是CONNECT报文。

  2. CONNACK确认连接请求

    服务端发送CONNACK报文响应从客户端收到的CONNECT报文。 服务端发送给客户端的第一个报文必须是CONNACK。如果客户端在合理的时间内没有收到服务端的CONNACK报文, 客户端应该关闭网络连接。合理的时间取决于应用的类型和通信基础设施。

  3. PUBLISH发布消息

    PUBLISH控制报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。

  4. PUBACK发布确认

    PUBACK报文是对QoS 1等级的PUBLISH报文的响应。

  5. PUBREC发布收到( QoS 2, 第一步)

    PUBREC报文是对QoS 2的PUBLISH报文的响应。 它是QoS 2等级协议交换的第二个报文。

  6. PUBREL发布释放( QoS 2, 第二步)

    PUBREL报文是对PUBREC报文的响应。 它是QoS 2等级协议交换的第三个报文。

  7. PUBCOMP发布完成( QoS 2, 第三步)

    PUBCOMP报文是对PUBREL报文的响应。 它是QoS 2等级协议交换的第四个也是最后一个报文。

  8. SUBSCRIBE订阅主题

    客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。 每个订阅注册客户端关心的一个或多个主题。 为了将应用消息转发给与那些订阅匹配的主题, 服务端发送PUBLISH报文给客户端。 SUBSCRIBE报文也( 为每个订阅) 指定了最大的QoS等级, 服务端根据这个发送应用消息给客户端。

  9. SUBACK订阅确认

    服务端发送SUBACK报文给客户端, 用于确认它已收到并且正在处理SUBSCRIBE报文。

  10. UNSUBSCRIBE取消订阅

    客户端发送UNSUBSCRIBE报文给服务端, 用于取消订阅主题。

  11. UNSUBACK取消订阅确认

    服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。

  12. PINGREQ心跳请求

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

    1. 在没有任何其它控制报文从客户端发给服务的时, 告知服务端客户端还活着。

    2. 请求服务端发送 响应确认它还活着。

    3. 使用网络以确认网络连接没有断开。

  13. PINGRESP心跳响应

    服务端发送PINGRESP报文响应客户端的PINGREQ报文。 表示服务端还活着。

  14. DISCONNECT断开连接

    DISCONNECT报文是客户端发给服务端的最后一个控制报文。 表示客户端正常断开连接。


标识位

位置:Byte 1中bits 3-0。

在不使用标识位的消息类型中,标识位被作为保留位。如果收到无效的标志时,接收端必须关闭网络连接:

(1)DUP:发布消息的副本。用来在保证消息的可靠传输,如果设置为1,则在下面的变长中增加MessageId,并且需要回复确认,以保证消息传输完成,但不能用于检测消息重复发送。

(2)QoS:发布消息的服务质量,即:保证消息传递的次数

Ø00:最多一次,即:<=1
Ø01:至少一次,即:>=1
Ø10:一次,即:=1
Ø11:预留

(3)RETAIN: 发布保留标识,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果没有那么推送至当前订阅者后释放。

剩余长度(Remaining Length)

地址:Byte 2。

剩余长度是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。MQTT控制报文总长度等于固定报头的长度加上剩余长度。


MQTT可变头

MQTT控制报文中包含一个可变头,它位于固定头和消息体之间。可变头的内容因报文类型而不同,较常的应用是作为包的标识。

可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。

部分类型MQTT控制报文的可变报头部分包含了2个字节的报文标识符字段,这些类型的包有:PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK。

需要报文标识符的MQTT控制报文如下表所示。

名字
CONNECT不需要
CONNACK不需要
PUBLISH需要(如果QoS>0)
PUBACK需要
PUBREC需要
PUBREL需要
PUBCOMP需要
SUBSCRIBE需要
SUBACK需要
UNSUBSCRIBE需要
UNSUBACK需要
PINGREQ不需要
PINGRESP不需要
DISCONNECT不需要
AUTH不需要

Payload消息体

Payload消息体位MQTT数据包的第三部分,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息:

  • (1)CONNECT,消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。
  • (2)SUBSCRIBE,消息体内容是一系列的要订阅的主题以及QoS。
  • (3)SUBACK,消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
  • (4)UNSUBSCRIBE,消息体内容是要订阅的主题。

原因码 Reason Code

原因码是一个单字节无符号数,用来指示一次操作的结果。小于0x80的原因码指示某次操作成功完成,通常用0来表示。大于等于0x80的原因码用来指示操作失败。

CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,DISCONNECT和AUTH控制报文的可变报头有一个单字节的原因码。SUBACK和UNSUBACK报文的载荷字段包含一个或多个原因码。

原因码如下表所示:

原因码名称报文
Dec(十进制)Hex(16进制)
00x00成功CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH
00x00正常断开DISCONNECT
00x00授权的QoS 0SUBACK
10x01授权的QoS 1SUBACK
20x02授权的QoS 2SUBACK
40x04包含遗嘱的断开DISCONNECT
160x10无匹配订阅PUBACK, PUBREC
170x11订阅不存在UNSUBACK
240x18继续认证AUTH
250x19重新认证AUTH
1280x80未指明的错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
1290x81无效报文CONNACK, DISCONNECT
1300x82协议错误CONNACK, DISCONNECT
1310x83实现错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
1320x84协议版本不支持CONNACK
1330x85客户标识符无效CONNACK
1340x86用户名密码错误CONNACK
1350x87未授权CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
1360x88服务端不可用CONNACK
1370x89服务端正忙CONNACK, DISCONNECT
1380x8A禁止CONNACK
1390x8B服务端关闭中DISCONNECT
1400x8C无效的认证方法CONNACK, DISCONNECT
1410x8D保活超时DISCONNECT
1420x8E会话被接管DISCONNECT
1430x8F主题过滤器无效SUBACK, UNSUBACK, DISCONNECT
1440x90主题名无效CONNACK, PUBACK, PUBREC, DISCONNECT
1450x91报文标识符已被占用PUBACK, PUBREC, SUBACK, UNSUBACK
1460x92报文标识符无效PUBREL, PUBCOMP
1470x93接收超出最大数量DISCONNECT
1480x94主题别名无效DISCONNECT
1490x95报文过长CONNACK, DISCONNECT
1500x96消息太过频繁DISCONNECT
1510x97超出配额CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT
1520x98管理行为DISCONNECT
1530x99载荷格式无效CONNACK, PUBACK, PUBREC, DISCONNECT
1540x9A不支持保留CONNACK, DISCONNECT
1550x9B不支持的QoS等级CONNACK, DISCONNECT
1560x9C(临时)使用其他服务端CONNACK, DISCONNECT
1570x9D服务端已(永久)移动CONNACK, DISCONNECT
1580x9E不支持共享订阅SUBACK, DISCONNECT
1590x9F超出连接速率限制CONNACK, DISCONNECT
1600xA0最大连接时间DISCONNECT
1610xA1不支持订阅标识符SUBACK, DISCONNECT
1620xA2不支持通配符订阅SUBACK, DISCONNECT

订阅主题–字符串匹配

在 MQTT 中,订阅仅仅是简单的字符串匹配。为提高处理效率,只允许如下两种通配符:

  • # 以递归方式匹配,直到字符串结束
  • + 匹配下一个 / 之前的内容
#发布主题:
> test/001/aaa
> test/001/bbb
> test/002/aaa
> test/002/bbb
> test/003/aaa
> test/003/bbb

#订阅主题:
> test/#        --匹配test下所有内容
> test/+/aaa    --匹配([test/001/aaa],[test/002/aaa],[test/003/aaa])

参考内容:

资料:

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值