MQTT protocol analysis summary (1)

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) payloadIt can be understood as the content of the message, which refers to the specific content that the subscriber wants to use
    Insert picture description here

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:
Insert picture description here
Insert picture description here

3.3 Payload

Certain MQTT control packetsContained in the last part of a message payload , for PUBLISHit 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

Guess you like

Origin blog.csdn.net/ZHONGCAI0901/article/details/111600721