MQTT报文分析

MQTT报文组成

MQTT报文由三部分组成,如下表所示。

​ 表1.1 MQTT报文构成

1Fixed Header固定报头,所有报文必须包含,长度可变
2Variable Header可变报头,不是所有报文都必须包含
3Payload报文负载,长度可变

Fixed Header

每一个MQTT报文都必须包含Fixed Header,其构成如表1.2所示

​ 表1.2 Fixed Header组成

byte1bit7-bit4:MQTT报文类型 bit3-bit0:报文类型标志位
byte2…剩余长度,整个MQTT报文出Fixed Header外的字节数

MQTT报文类型

如表1.3所示

​ 表1.3 MQTT报文类型

报文类型方向描述
Reserved0禁止保留
CONNECT1Client端到Broker端链接请求
CONNACT2Broker端到Client端链接请求响应
PUBLISH3双向消息发布
PUBACK4双向QoS1等级消息接收确认
PUBREC5双向QoS等级为2的消息的第一步,即对PUBLISH报文的响应
PUBREL6双向QoS等级为2的消息的第二步,即对PUBREC报文的响应
PUBCOMP7双向QoS等级为2的消息的第三步,即对PUBREL报文的响应,标志着一次QoS消息发布的完成
SUBSCRIBE8Client端到Broker端消息订阅请求
SUBACK9Broker端到Client端消息订阅请求响应
UNSUBSCRIBE10Client端到Broker端消息订阅取消请求
UNSUBACK11Broker端到Client端消息订阅取消请求响应
PINGREQ12Client端到Broker端心跳请求
PINGRESP13Broker端到Client端心跳请求响应
DISCONNECT14Client端到Broker端链接断开请求
Reserved15禁止保留

报文类型标志位

控制报文固定报头标志bit3bit2bit1bit0
CONNECTReserved0000
CONNACKReserved0000
PUBLISHUsed in MQTT3.1.1DUP1:控制报文重复分发标志Qos2:PUBLISH报文QoS质量等级Qos2:PUBLISH报文QoS质量等级RETAIN:PUBLISH报文
PUBACKReserved0000
PUBRECReserved0000
PUBRELReserved0000
PUBCOMPReserved0000
SUBSCRIBEReserved0000
SUBACKReserved0000
UNSUBSCRIBEReserved0000
UNSUBACKReserved0000
PINGREQReserved0000
PINGRESPReserved0000
DISCONNECTReserved0000

剩余长度

剩余长度(Remaining Length)表示当前报文剩余部分的字节数,包括可变报头和负载的数据,不包括用于编码剩余长度字段本身的字节数。剩余长度字段使用一个变长度编码方案,对小于128的值它使用单字节编码。更大的值按下面的方式处理。低7位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个
字节可以编码128个数值和一个延续位(continuation bit)。剩余长度字段最大4个字节。

解码计算方法

	int recvdlen = 0;
	int multiplier = 1;
	int remainlength = 0; //剩余长度
	unsigned char byte = 0;
	do{
		recvdlen = read(client->socket, &byte, 1);
		if(recvdlen != 1){
			DEBUG_INFO("read data error \n");
			return -1;
		}
		remainlength += (byte & 0x7F)*multiplier;
		multiplier *= 0x80;
		if(multiplier > 0x80*0x80*0x80){
			DEBUG_INFO("calculate remain length error\n");
			return -1;
		}
}while((byte & 0x80) != 0);

编码计算方法

int x = 300; //x:remain length
unsigned char encodeByte = 0; //编码后的字节
do{
   encodedByte = X % 128;
   x = x / 128;
    if(x > 0){
        encodeByte = encodeByte | 128;
    }     
}while(x > 0);

Variable Header

某些MQTT控制报文在固定包头和负载之间,包含一个可变报头。可变报头的内容根据
报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型
的报文里。

报文标识符Packet identifier

表2.1

byte1报文标识符MLB
byte2报文标识符SLB

很多控制报文的可变报头部分包含一个两字节的报文标识符字段,这些报文包括PUBLISH(QoS > 0时), PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCIBE,UNSUBACK。

SUBSCRIBE,UNSUBSCRIBE和PUBLISH(QoS大于0)控制报文必须包含一个非零的16位报文标识符(Packet Identifier)。客户端每次发送一个新报文时都必须分配一个未使用的报文标识符 。如果一个客户端要重发这个特殊的控制报文,必须使用相同的标识符。当客户端处理完这个报文对应的确认后,报文标识符才可释放重用。

QoS 1的PUBLISH对应的是PUBACK,QoS 2的PUBLISH对应的是PUBCOMP,与SUBSCRIBE或UNSUBSCRIBE对应的分别是SUBACK或UNSUBACK 。PUBACK, PUBREC, PUBREL报文必须包含与最初发送的PUBLISH报文相同的报文标识符。同样,SUBACK和UNSUBACK必须包含SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符。

有效载荷payload

某些MQTT控制报文在报文的最后部分包含一个有效载荷,将在每个报文的详细分析中具体描述。表格 3.1列出了具有有效载荷的控制报文。

表3.1

报文类型有效载荷
CONNECT需要
CONNACK不需要
PUBLISH可选
PUBACK不需要
PUBREC不需要
PUBREL不需要
PUBCOMP不需要
SUBSCRIBE需要
SUBACK需要
UNSUBSCRIBE需要
UNSUBACK不需要
PINGREQ不需要
PINGRESP不需要
DISCONNECT不需要

UTF-8编码

MQTT协议报文中的字符,使用UTF-8编码,后续对每个MQTT报文进行分析的文章会碰到。

UTF-8是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部份修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。

与ASCII相比,UTF-8在每个字符队列前加入了两个字节的长度字段,用来表示这个字符队列的长度(注意该字符队列不是字符串,不包括’\0’)。

二进制位描述
byte1字符串长度MLB
byte2字符串长度SLB
byte3…字符队列(ASCII编码)

引用

1 MQTT协议中文版本》:https://mcxiaoke.gitbooks.io/mqtt-cn/content/

2 百度百科:https://baike.baidu.com/item/UTF-8/481798?fr=aladdin

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值