Article Directory
related articles
1. "MQTT Protocol Analysis Summary (1)"
2. "MQTT Protocol Analysis Summary (2)"
3. "[IoT] How to Connect to Baidu IoT Cloud"
4. "[FreeRTOS] MQTT based on STM32 transplantation of LWIP 2.1.2 》
1 Introduction
MQTT 3 (current version3.1.1
) is currently the most widely usedMQTT protocol standard. Although the MQTT 5 standard has been released, and has brought some exciting new features, but in the entire application scenario, the industry 's transition from version 3 to 5 may continue for some time. The biggest advantage of MQTT is that it can provide real-time and reliable messaging services for remote devices with very few codes and limited bandwidth. As a low-overhead, low-bandwidth instant messaging protocol, MQTT has a wide range of applications in the Internet of Things, small devices, and mobile applications.
2. MQTT protocol implementation method
The realization of the MQTT protocol requires the completion of the communication between the client and the server . In the communication process, there are three identities in the MQTT protocol : publisher (Publish) , agent (Broker server) , and subscriber (Subscribe) . Among them, the publisher and subscriber of the message are both clients, the message broker is the server, and the message publisher can be the subscriber at the same time.
The messages transmitted by MQTT are divided into two parts: Topic and payload :
- (1)
Topic
, can be understood as the type of message, the subscriber订阅(Subscribe)
will receive the topic消息内容(payload)
; - (2)
payload
It can be understood as the content of the message, which refers to the specific content that the subscriber wants to use
3. MQTT control message format
MQTT protocolWorking on TCP , the end and the agent exchange predefined control messages to complete the communication. The MQTT message consists of 3 parts, which appear in the following order:
Fixed header | Fixed header, all control messages include |
---|---|
Variable header | Variable header, part of the control message contains |
Payload | Payload, part of the control message contains |
3.1 Format of the fixed header
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | Types of MQTT control packets | Flag bit used to specify the type of control message | ||||||
byte 2... | Remaining length |
- Types of MQTT control packets
first name | value | Message flow direction | description |
---|---|---|---|
Reserved | 0 | Prohibit | Keep |
CONNECT | 1 | Client to server | Client requests to connect to the server |
CONNACK | 2 | Server to client | Connection message confirmation |
PUBLISH | 3 | Both directions are allowed | release the news |
PUBACK | 4 | Both directions are allowed | Acknowledgement of QoS 1 message release |
PUBREC | 5 | Both directions are allowed | Release and receive (the first step to ensure delivery) |
PUBREL | 6 | Both directions are allowed | Release and release (guaranteed delivery second step) |
PUBCOMP | 7 | Both directions are allowed | QoS 2 news release completed (guaranteed the third step of interaction) |
SUBSCRIBE | 8 | Client to server | Client subscription request |
SUBACK | 9 | Server to client | Subscription request message confirmation |
UNSUBSCRIBE | 10 | Client to server | Client unsubscribe request |
UNSUBACK | 11 | Server to client | Unsubscribe message confirmation |
PINGREQ | 12 | Client to server | Heartbeat request |
PINGRESP | 13 | Server to client | Heartbeat response |
DISCONNECT | 14 | Client to server | Client disconnected |
Reserved | 15 | Prohibit | Keep |
-
Remaining length
position: starting from the second byte.The remaining length (Remaining Length) represents the number of bytes in the remaining part of the current message, including variable headers and payload data. The remaining length does not include the number of bytes used to encode the remaining length field itself.
Use one for the remaining length fieldVariable length codingScheme, it uses single-byte encoding for values less than 128. Larger values are handled in the following way. The lower 7 significant bits are used to encode data, and the most significant bit is used to indicate whether there are more bytes. Therefore, each byte can encode 128 values and a continuation bit . The remaining length field has a maximum of 4 bytes .
Number of bytes | Minimum | Max |
---|---|---|
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) |
Respectively (the lower 7 bits of each byte are used to encode data, and the highest bit is the flag bit):
- For 1 byte, from 0 (0x00) to 127 (0x7f)
- For 2 bytes, from 128 (0x80, 0x01) to 16383 (0Xff, 0x7f)
- At 3 bytes, from 16384 (0x80, 0x80, 0x01) to 2097151 (0xFF, 0xFF, 0x7F)
- For 4 bytes, from 2097152 (0x80, 0x80, 0x80, 0x01) to 268435455 (0xFF, 0xFF, 0xFF, 0x7F)
The algorithm for non-negative integer X using the variable-length coding scheme is as follows:
do
encodedByte = X MOD 128
X = X DIV 128
// if there are more data to encode, set the top bit of this byte
if ( X > 0 )
encodedByte = encodedByte OR 128
endif
'output' encodedByte
while ( X > 0 )
MOD is modular operation, DIV is integer division, OR is bitwise operation or (%, /, | in C language)
The corresponding C language code is as follows:
/**
* Encodes the message length according to the MQTT algorithm
* @param buf the buffer into which the encoded data is written
* @param length the length to be encoded
* @return the number of bytes written to buffer
*/
int MQTTPacket_encode(unsigned char* buf, int length)
{
int rc = 0;
FUNC_ENTRY;
do
{
char d = length % 128;
length /= 128;
/* if there are more digits to encode, set the top bit of this digit */
if (length > 0)
d |= 0x80;
buf[rc++] = d;
} while (length > 0);
FUNC_EXIT_RC(rc);
return rc;
}
The variable-length decoding scheme algorithm for the remaining length field is as follows:
multiplier = 1
value = 0
do
encodedByte = 'next byte from stream'
value += (encodedByte AND 127) * multiplier
if (multiplier > 128*128*128)
throw Error(Malformed Remaining Length)
multiplier *= 128
while ((encodedByte AND 128) != 0)
AND is the bit operation and (& in C language) when
this algorithm terminates, value contains the value of the remaining length.
The corresponding C language code is as follows:
/**
* Decodes the message length according to the MQTT algorithm
* @param getcharfn pointer to function to read the next character from the data source
* @param value the decoded length returned
* @return the number of bytes read from the socket
*/
int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
{
unsigned char c;
int multiplier = 1;
int len = 0;
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
FUNC_ENTRY;
*value = 0;
do
{
int rc = MQTTPACKET_READ_ERROR;
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
{
rc = MQTTPACKET_READ_ERROR; /* bad data */
goto exit;
}
rc = (*getcharfn)(&c, 1);
if (rc != 1)
goto exit;
*value += (c & 127) * multiplier;
multiplier *= 128;
} while ((c & 128) != 0);
exit:
FUNC_EXIT_RC(len);
return len;
}
3.2 Variable header
someMQTT control messageContains a variable header part. It is between the fixed header and the payload. The content of the variable header varies according to the message type. The message identifier ( Packet Identifier
) field of the variable header exists in multiple types of messages.
Note: The variable header not only refers to the message identifier , the following is only used as an example. Different MQTT message types have different variable headers.
The message identifier byte is as follows:
Bit | 7 - 0 |
---|---|
byte 1 | Message identifier MSB |
byte 2 | Message identifier LSB |
The variable header part of many control messages contains a two-byte message identifier field . The control messages that require message identifiers are listed in the following table:
Control message | Message identifier field |
---|---|
CONNECT | Not needed |
CONNACK | Not needed |
PUBLISH | Required (if QoS> 0) |
PUBACK | need |
PUBREC | need |
PUBREL | need |
PUBCOMP | need |
SUBSCRIBE | need |
SUBACK | need |
UNSUBSCRIBE | need |
UNSUBACK | need |
PINGREQ | Not needed |
PINGRESP | Not needed |
DISCONNECT | Not needed |
The client and the server allocate message identifiers independently of each other. Therefore, the combination of the client and the server using the same message identifier can achieve concurrent message exchange. Examples are as follows:
3.3 Payload
Certain MQTT control packetsContained in the last part of a message payload , for PUBLISH
it is the application message payload.
Control Packets that contain a Payload
Control message | Payload |
---|---|
CONNECT | need |
CONNACK | Not needed |
PUBLISH | Optional |
PUBACK | Not needed |
PUBREC | Not needed |
PUBREL | Not needed |
PUBCOMP | Not needed |
SUBSCRIBE | need |
SUBACK | need |
UNSUBSCRIBE | need |
UNSUBACK | Not needed |
PINGREQ | Not needed |
PINGRESP | Not needed |
DISCONNECT | Not needed |
4. MQTT control message
Each specific message is introduced in the following article: "MQTT Protocol Analysis Summary (2)"
5. Reference materials
Chinese version of MQTT 5.0 protocol:
https://github.com/twoFiveOneTen/MQTT_V5
MQTT Version 5.0:
http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02 .htm
MQTT 3.1.1 protocol Chinese version:
https://github.com/mcxiaoke/mqtt
MQTT Version 3.1.1:
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt -v3.1.1-os.html