In MQTT protocol, a control message (packet) structure in accordance with the order points before and after the following three parts:
Structure name | Chinese name | explain |
---|---|---|
Fixed header | Fixed header | The beginning part of the message, all messages are included in this section |
Variable header | Variable header | Additional portions of the fixed packets, some packets do not have this section |
Payload | Payload | Information content need to carry some message without this section |
The figure is a schematic structural diagram MQTT control message (packet) format:
1, the fixed header (Fixed header):
Fixed header MQTT present in all packets, and control data indicating the packet type based signs. Fixed header from at least 2 bytes, the following format:
Bit (bit number) | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Byte1 (the first byte) | Type represents a combination MQTT control packets (data packets) | Control flag (Flags) message, understood as one of the properties | ||||||
Byte2 (second byte onwards) | Remaining length, the number of bytes of the remaining portion of the current packet, including a header and a payload of variable |
1.1, the control packet type (Control Packet type):
The fixed header of the first byte of the upper four bits (bit No. 7-4) is the representative type of the control packet, i.e. the packet is what to do with. 7-4 is a binary number bits (i.e. between 1111--0000) value combination, to represent specific meanings, as follows:
Bit No. 7-4 | Decimal value | Packet type | Packets allowed to initiate direction | Description packets |
---|---|---|---|---|
0000 | 0 | Reserved | Ban | Reservations are not available |
0001 | 1 | CONNECT | Client - → server | The client requests a connection to the server proxy service |
0010 | 2 | CONNACK | Client ← - server | Reply to the confirmation of the connection request packet |
0011 | 3 | PUBLISH | Client server ← → | Post subject news |
0100 | 4 | PUBACK | Client server ← → | Release confirmed that QoS = 1, the response to the confirmation PUBLISH |
0101 | 5 | PUBREC | Client server ← → | Posted received a QoS = 2, PUBLISH response to confirmation, is the first step to achieve QoS = 2 |
0110 | 6 | PUBREL | Client server ← → | Release release, it is QoS = 2, the response to PUBREC confirmation, is the second step to achieve QoS = 2 |
0111 | 7 | PUBCOMP | Client server ← → | Complete release, is QoS = 2, in response to the confirmation PUBREL, QoS = 2 is realized in the third step |
1000 | 8 | SUBSCRIBE | Client - → server | Clients subscribe to a topic, one can subscribe to one or more topics (using wildcards) |
1001 | 9 | SUBACK | Client ← - server | Subscribe to complete the confirmation, confirmation is a response to SUBSCRIBE |
1010 | 10 | UNSUBSCRIBE | Client - → server | Unsubscribe, client-initiated unsubscribe to a topic |
1011 | 11 | UNSUBACK | Client ← - server | Unsubscribe confirmation, confirmation is a response to UNSUBSCRIBE |
1100 | 12 | PINGREQ | Client - → server | Heartbeat, indicating that the data packet is for the client to inform the server is still connected to normal |
1101 | 13 | PINGRESP | Client ← - server | Heartbeat response indicates the server has successfully received the client's heartbeat |
1110 | 14 | DISCONNECT | Client - → server | Disconnect, client-side notification service, you need to disconnect your current network connection |
1111 | 15 | Reserved | Ban | Reservations are not available |
1.2, the flag (Flags):
The fixed header of the first byte of the lower 4 bits (bits 3-0) contains a control for each packet type specific MQTT flag must be used with the type of control message matching the corresponding, otherwise the server may refuse service proxy service on or off open connection. Specifically the following table (reserved flag must be set according to the value in the table):
Packet type | Flag type | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|
CONNECT | Retention | 0 | 0 | 0 | 0 |
CONNACK | Retention | 0 | 0 | 0 | 0 |
PUBLISH | use | Is a duplicate made | High quality of service | Low quality of service | Whether to save messages |
PUBACK | Retention | 0 | 0 | 0 | 0 |
PUBREC | Retention | 0 | 0 | 0 | 0 |
PUBREL | Retention | 0 | 0 | 1 | 0 |
PUBCOMP | Retention | 0 | 0 | 0 | 0 |
SUBSCRIBE | Retention | 0 | 0 | 1 | 0 |
SUBACK | Retention | 0 | 0 | 0 | 0 |
UNSUBSCRIBE | Retention | 0 | 0 | 1 | 0 |
UNSUBACK | Retention | 0 | 0 | 0 | 0 |
PINGREQ | Retention | 0 | 0 | 0 | 0 |
PINGRESP | Retention | 0 | 0 | 0 | 0 |
DISCONNECT | Retention | 0 | 0 | 0 | 0 |
Note: For use "if" is the actual description of the Boolean type, 0 for no, 1 for true;
1.3, the first byte of each packet type specific values:
High fixed header packet type 4 bits and lower 4 bits of the flags together, the first byte is eventually a specific value. In order to better understand the specific value of the first byte is how to get out, the following table lists the specific values of the different types of packets and a packet different signs:
Packet type | Marking Role | Binary values | Decimal value | Hexadecimal value |
---|---|---|---|---|
CONNECT | Connected to the server | 00010000 | 16 | 0x10 |
CONNACK | The connection is successful confirmation | 00100000 | 32 | 0x20 |
PUBLISH | The new release level 0 is not saved | 00110000 | 48 | 0x30 |
PUBLISH | The new release level 0 to be saved | 00110001 | 49 | 0x31 |
PUBLISH | The new release level 1 without saving | 00110010 | 50 | 0x32 |
PUBLISH | The new release level 1 to be saved | 00110011 | 51 | 0x33 |
PUBLISH | The new release Level 2 are not saved | 00110100 | 52 | 0x34 |
PUBLISH | The new release level 2 to be saved | 00110001 | 53 | 0x35 |
PUBLISH | 重发等级2不保存 | 00111000 | 56 | 0x38 |
PUBLISH | 重发等级2需保存 | 00111001 | 57 | 0x39 |
PUBACK | 等级1发布成功 | 01000000 | 64 | 0x40 |
PUBREC | 等级2发布收到 | 01010000 | 80 | 0x50 |
PUBREL | 等级2发布释放 | 01100010 | 98 | 0x62 |
PUBCOMP | 等级2发布完成 | 01110000 | 112 | 0x70 |
SUBSCRIBE | 订阅主题 | 10000010 | 130 | 0x82 |
SUBACK | 订阅完成确认 | 10010000 | 144 | 0x90 |
UNSUBSCRIBE | 取消订阅 | 10100010 | 162 | 0xA2 |
UNSUBACK | 取消完成确认 | 10110000 | 176 | 0xB0 |
PINGREQ | 心跳包 | 11000000 | 192 | 0xC0 |
PINGRESP | 心跳回复 | 11010000 | 208 | 0xD0 |
DISCONNECT | 断开网络连接 | 11100000 | 224 | 0xE0 |
注:关于发布主题还有其他情况这里就没有全部列出,根据表中的规律就可以计算出实际的值了。
1.3、剩余长度(Remaining Length):
剩余长度是从第二个字节开始,最多允许占用四个字节。描述本次传送的应用消息在剩余长度字节之后(不包括剩余长度字节本身)还有多少个字节,包括可变报头(有的报文没有这部分) + 有效载荷(有的报文没有这部分)的所有字节数量。
根据上面描述,剩余长度属于变长的编码规则,也就是它可能是1-4个字节中的任何一种情况,那么怎样知道当前这个报文的剩余长度是占用了几个字节的呢?如果不能确定,那么接收方就无法正确解析数据了。所以MQTT协议规定剩余长度的每个字节的最高位(也就是7号位)作为是否还有下一个字节剩余长度的标志位,不做长度数值的表述位。这样每给剩余长度字节最大代表长度值就是127(二进制 1111111 的值)了,因为只有7个位表示长度了。向后每增加一个字节都代表前一个字节满值再加1的倍数,四个字节的剩余长度代表的长度值最大可为268435455。
如果剩余长度值不大于127,则只用一个字节表示,例如121,则剩余长度字节的二进制是01111001,含义见下表:
7号位 | 6-0号位 |
---|---|
0 | 1111001 |
接下来没有剩余长度字节了 | 剩余长度是:121 |
如果剩余长度值大于127小于16384,则需用两个字节表示,例如15971,则剩余长度两字节具体值则是0xE3 0x7C(11100011 01111100),含义见下表:
1字节7号位 | 1字节6-0号位 | 2字节7号位 | 2字节6-0号位 |
---|---|---|---|
1 | 1100011 | 0 | 1111100 |
后面还有字节描述长度 | 本子节描述长度:99 | 后面没有长度字节了 | 本字节描述长度:124 * 128 = 15872 |
两个字节代表的长度值相加 99 + 15872 = 15971,这既是完整的剩余长度值了。后面这个字节每增加1,则代表剩余长度值增加128。也就是前面字节的低7位值满都为1(127)再加1,就到后面字节加1,前面字节低7位归0。再加满再到后面字节加1,以此类推。所以两个字节可以表述的最大值是(11111111 01111111)127+(127*128) = 16383。
由于使用了两个字节表述剩余长度,那么前面的字节的最高位7号位就要置1,以告诉解析程序后面的字节还要按照剩余长度来计算。
如果剩余长度值大于16383小于2097152,则需用三个字节表示,例如2097150,则剩余长度三字节具体值则是0xFE 0xFF 0x7F(11111110 11111111 01111111),含义见下表:
1字节7号位 | 1字节6-0号位 | 2字节7号位 | 2字节6-0号位 | 3字节7号位 | 3字节6-0号位 |
---|---|---|---|---|---|
1 | 1111110 | 1 | 1111111 | 0 | 1111111 |
还有长度字节 | 长度:126 | 还有长度字节 | 长度:127 * 128 = 16256 | 长度最后字节 | 长度:127 * 16384 = 2080768 |
三个字节代表的长度值相加 126 + 16256 + 2080768 = 2097150,这既是完整的剩余长度值了。3字节每增加1,则代表剩余长度值增加16384,即前两个字节满值再加1。四字节的原理也是这样向后推导,这里就不再列举了。
剩余长度使用1-4个字节可以描述的长度范围见下表:
字节数 | 最小值10/16进制 | 最小值2进制 | 最大值10/16进制 | 最大值2进制 | |
---|---|---|---|---|---|
1 | 0(0x00) | 00000000 | 127(0x7F) | 01111111 | |
2 | 128(0x80,0x01) | 10000000 00000001 | 16383(0xFF,0x7F) | 11111111 01111111 | |
3 | 16384(0x80,0x80,0x01) | 10000000 10000000 00000001 | 2097151(0xFF,0xFF,0x7F) | 11111111 11111111 01111111 | |
4 | 2097152(0x80,0x80,0x80,0x01) | 10000000 10000000 10000000 00000001 | 268435455(0xFF,0xFF,0xFF,0x7F) | 11111111 11111111 11111111 01111111 |
2、可变报头(Variable header):
可变报头在固定报头与有效负载之间,不是所有的报文都有可变报头。报文类型不同可变报头的内容也不同。后面会对各报文的可变报头逐一讨论。某些类型的报文中的可变报头还包含报文标识符(Packet Identifier)字段。
2.1、报文标识符(Packet Identifier):
报文标识符,一定程度上相当于是每个报文的唯一ID,用于识别报文身份的。重复发送报文时,必须使用相同的报文标识符。在需要应答的控制报文里,标识符可以区分是应答的哪个报文。某些控制报文的可变报头部分包含一个两字节的报文标识符字段。这些报文分别是PUBLISH(QoS > 0时), PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE, SUBACK,UNSUBSCRIBE,UNSUBACK。
需要使用标识符的报文,发送方在每次发送一个新的报文时,必须分配一个没有使用过的报文标识符。报文标识符固定使用两个字节,按照双字节读值可用范围是0-65535(00000000 00000000 -- 11111111 11111111)。
3、有效载荷(Payload):
在一些需要携带用户自定义的应用消息的MQTT控制报文中,会将这些信息放在报文的最后部分,称之为有效载荷。对于PUBLISH来说有效载荷就是应用消息。不同的控制报文有效载荷内容不同,后面会在分别介绍控制报文时具体讨论。下表列出哪些控制报文有包含有效载荷:
控制报文 | 有效载荷 |
---|---|
CONNECT | 需要 |
CONNACK | 不 需要 |
PUBLISH | 可选,可以零长度 |
PUBACK | 不需要 |
PUBREC | 不需要 |
PUBREL | 不需要 |
PUBCOMP | 不需要 |
SUBSCRIBE | 需要 |
SUBACK | 需要 |
UNSUBSCRIBE | 需要 |
UNSUBACK | 不需要 |
PINGREQ | 不需要 |
PINGRESP | 不需要 |
DISCONNECT | 不需要 |
本节完,待续......