MQTT协议结构

MQTT协议结构

前言

最近在了解MQTT协议相关的内容,内容有点多,特此把MQTT协议,以及其从服务端到客户端的流程整理出来,记录如下。

一,MQTT协议介绍

1.1 术语 Terminology

本规范中用到的关键字 必须 MUST,不能 MUST NOT,要求 REQUIRED,将会 SHALL,不会 SHALL NOT,应该 SHOULD,不应该 SHOULD NOT,推荐 RECOMMENDED,可以 MAY,可选 OPTIONAL 都是按照 IETF RFC 2119 [RFC2119] 中的描述解释。

网络连接 Network Connection

MQTT使用的底层传输协议基础设施。

  • 客户端使用它连接服务端。
  • 它提供有序的、可靠的、双向字节流传输

1.2MQTT协议介绍

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,它是一种轻量级的、基于代理的“发布/订阅”模式的消息传输协议。其具有协议简洁小巧可扩展性强省流量省电等优点,而且已经有PHP,JAVA,Python,C,C#,Go等多个语言版本,基本可以使用在任何平台上,几乎可以把所有联网物品和外部连接起来,所以特别适合用来当做物联网的通信协议,实用的场景有遥感数据、汽车、智能家居、智慧城市、医疗医护等等。

MQTT特点

​ MQTT协议是为*大量计算能力有限*,且工作在*低带宽*、***不可靠的网络***的远程传感器和控制***设备通讯***而设计的协议,它具有以下主要的几项特性:

1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合;

2、对负载内容屏蔽的消息传输;

3、使用 TCP/IP 提供网络连接;

4、有三种消息发布服务质量:

​ “至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。

​ “至少一次”,确保消息到达,但消息重复可能会发生。

​ “只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。

5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;

6、使用 Last Will (遗嘱)和 Testament 特性通知有关各方客户端异常中断的机制;

1.消息模型

MQTT是一种基于代理的发布/订阅的消息协议。与请求/回答这种同步模式不同,发布/订阅模式解耦了发布消息的客户(发布者)与订阅消息的客户(订阅者)之间的关系,这意味着发布者和订阅者之间并不需要直接建立联系。一个发布者可以对应多个订阅者,当发布者发生变化的时候,他可以将消息一一通知给所有的订阅者。这种模式提供了更大的网络扩展性和更动态的网络拓扑

个人理解为一个对象可以有多个订阅者,只负责推送消息,接受对象凭借是否订阅为接受条件

此外运用MQTT协议,设备可以很方便地连接到物联网云服务,管理设备并处理数据,最后应用到各种业务场景,如下图所示

img

2.服务质量

MQTT提供三种质量的服务:

​ 至多一次(qos = 0),可能会出现丢包的现象。使用在对实时性要求不高的情况。这一级别可应用于如下情景,如环境传感器数据,丢失一次读记录无所谓,因为很快下一次读记录就会产生。

​ 至少一次(qos = 1),保证包会到达目的地,但是可能出现重包。

​ 正好一次(qos = 2),保证包会到达目的地,且不会出现重包的现象。这一级别可用于如计费系统等场景,在计费系统中,消息丢失或重复可能会导致生成错误的费用。

img

3.主题与通配符

主题名称(Topic name)用来标识已发布消息的信息的渠道。订阅者用它来确定接收到所关心的信息。它是一个分层的结构,用斜线“/”作为分隔符(这个有点类似于restful风格)。主题还可以通过通配符进行过滤。其中,+可以过滤一个层级,而#只能出现在主题最后表示过滤任意级别的层级。值得注意的是***MQTT允许使用通配符订阅主题,但是并不允许使用通配符广播***。

举个例子:

building-b/floor-5:代表B楼5层的设备。

+/floor-5:代表任何一个楼的5层的设备。

building-b/#:代表B楼所有的设备。

4.遗嘱

当一个客户端断开连接的时候,它希望客户端可以发送它指定的消息。该消息和普通消息的结构相同。通过设置该位并填入和信息相关的内容即可(后面会有介绍)。

5.消息类型
消息类型 类型 编码说明
reserved 0 保留
connect 1 客户端到服务端的连接请求
connACK 2 服务端对连接请求的响应
publish 3 发布消息
puback 4 新发布消息确认,是QoS 1给PUBLISH消息的回复
pubRec 5 QoS 2消息流的第一部分,表示消息发布已记录
pubRel 6 QoS 2消息流的第二部分,表示消息发布已释放
pubComp 7 QoS 2消息流的第三部分,表示消息发布完
subscribe 8 客户端订阅某个主题
subBack 9 对于SUBSCRIBE消息的确认
unsubscribe 10 客户端终止订阅的消息
unsubBack 11 对于UNSUBSCRIBE消息的确认
pingReq 12 心跳
pingResp 13 确认心跳
disconnect 14 客户端终止连接前通知MQTT代理
reserved 15 保留

二,MQTT控制报文格式 MQTT Control Packet format

2.1 MQTT控制报文的结构 Structure of an MQTT Control Packet

MQTT协议通过交换预定义的MQTT控制报文来通信。这一节描述这些报文的格式。

MQTT控制报文由三部分组成,按照 图例 2.1 –MQTT控制报文的结构 描述的顺序:

图例 2.1 –MQTT控制报文的结构
Fixed header 固定报头,所有控制报文都包含
Variable header 可变报头,部分控制报文包含
Payload 有效载荷,部分控制报文包含

2.2 固定报头 Fixed header

每个MQTT控制报文都包含一个固定报头。图例 2.2 -固定报头的格式 描述了固定报头的格式。

图例 2.2 -固定报头的格式
Bit 7 6 5 4 3 2 1 0
byte 1 MQTT控制报文的类型 用于指定控制报文类型的标志位
byte 2… 剩余长度
2.2.1 MQTT控制报文的类型 MQTT Control Packet type

**位置:**第1个字节,二进制位7-4。

表示为4位无符号值,这些值的定义见 表格 2.1 -控制报文的类型

表格 2.1 -控制报文的类型
名字 报文流动方向 描述
Reserved 0 禁止 保留
CONNECT 1 客户端到服务端 客户端请求连接服务端
CONNACK 2 服务端到客户端 连接报文确认
PUBLISH 3 两个方向都允许 发布消息
PUBACK 4 两个方向都允许 QoS 1消息发布收到确认
PUBREC 5 两个方向都允许 发布收到(保证交付第一步)
PUBREL 6 两个方向都允许 发布释放(保证交付第二步)
PUBCOMP 7 两个方向都允许 QoS 2消息发布完成(保证交互第三步)
SUBSCRIBE 8 客户端到服务端 客户端订阅请求
SUBACK 9 服务端到客户端 订阅请求报文确认
UNSUBSCRIBE 10 客户端到服务端 客户端取消订阅请求
UNSUBACK 11 服务端到客户端 取消订阅报文确认
PINGREQ 12 客户端到服务端 心跳请求
PINGRESP 13 服务端到客户端 心跳响应
DISCONNECT 14 客户端到服务端 客户端断开连接
Reserved 15 禁止 保留
2.2.2 标志 Flags

保证消息可靠传输,默认为0,只占用一个字节,表示第一次发送。不能用于检测消息重复发送等。适用于客户端或服务器端尝试重发***PUBLISH***(发送消息), *PUBREL*(QoS 2消息流的第二部分,表示消息发布已释放), *SUBSCRIBE*(客户端订阅某个主题) 或 UNSUBSCRIBE(客户端终止订阅的消息)消息,注意需要满足以下条件:当 QoS > 0时消息需要回复确认,此时,在可变头部需要包含消息ID。当值为1时,表示当前消息先前已经被传送过。

QoS(Quality of Service,服务质量)

使用两个二进制表示PUBLISH类型消息:

img

RETAIN(保持)

仅针对PUBLISH消息。不同值,不同含义:

0:仅仅为当前订阅者推送此消息。

1:表示发送的消息需要一直持久保存(不受服务器重启影响),不但要发送给当前的订阅者,并且以后新来的订阅了此Topic name的订阅者会马上得到推送。

另外对于新加入的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送。

Remaining Length(剩余长度)

在当前消息中剩余的byte(字节)数,包含可变头部和负荷(称之为内容/body,更为合适)。单个字节最大值:01111111,16进制:0x7F,10进制为127。单个字节为什么不能是11111111(0xFF)呢?因为MQTT协议规定,第八位(最高位)若为1,则表示还有后续字节存在。

同时MQTT协议最多允许4个字节表示剩余长度。那么最大长度为:0xFF,0xFF,0xFF,0x7F。

**二进制表示为:**11111111,11111111,11111111,01111111

**十进制:**268435455 byte=261120KB=256MB=0.25GB

四个字节之间值的范围:

img

2.2.3 剩余长度 Remaining Length

**位置:**从第2个字节开始。

剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。

剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码128个数值和一个延续位(continuation bit)。剩余长度字段最大4个字节。

非规范评注

例如,十进制数64会被编码为一个字节,数值是64,十六进制表示为0x40,。十进制数字321(=65+2*128)被编码为两个字节,最低有效位在前。第一个字节是 65+128=193。注意最高位为1表示后面至少还有一个字节。第二个字节是2。

非规范评注

这允许应用发送最大256MB(268,435,455)大小的控制报文。这个数值在报文中的表示是:0xFF,0xFF,0xFF,0x7F。

表格 2.4剩余长度字段的大小展示了剩余长度字段所表示的值随字节增长。

表格 2.4剩余长度字段的大小 Size of Remaining Length field
字节数 最小值 最大值
1 0 (0x00) 127 (0x7F)
2 128 (0x80, 0x01) 16 383 (0xFF, 0x7F)
3 16 384 (0x80, 0x80, 0x01) 2 097 151 (0xFF, 0xFF, 0x7F)
4 2 097 152 (0x80, 0x80, 0x80, 0x01) 268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

分别表示(每个字节的低7位用于编码数据,最高位是标志位):

  • 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)

非规范评注

非负整数X使用变长编码方案的算法如下:

```do encodedByte 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值