In Introduction to MQTT 5.0 Packet, we introduced that MQTT packets are composed of three parts: Fixed Header, Variable Header, and Payload, as well as common concepts in MQTT packets such as Variable Byte Integer and Property. Now, we will further introduce the composition of each type of packet according to its actual use. First, we will focus on the packets used to establish an MQTT connection.
If we want to use MQTT for communication, the first step must be to establish an MQTT connection. Establishing an MQTT connection requires the use of two control packets, which are the CONNECT packet and the CONNACK packet. The CONNECT packet is the first control packet sent by the client to the server after establishing a network connection and is used to initiate a connection request. The server will return a CONNACK packet to inform the client of the connection result.
Sample Packets
We use MQTTX CLI to initiate a connection to a Public MQTT server. In this connection, we set the protocol version to MQTT 5.0, Clean Start to 1, Session Expiry Interval to 300 seconds, Keep Alive to 60, and the username and password to admin and public respectively. The corresponding MQTTX CLI command is:
mqttx conn --hostname broker.emqx.io --mqtt-version 5 \
--session-expiry-interval 300 --keepalive 60 --username admin --password public
Below is the CONNECT packet sent out by MQTTX CLI captured using the Wireshark tool:
The following is the CONNECT packet sent by MQTTX CLI captured using Wireshark. In Linux, you can use tcpdump to capture the packet first, and then import it to Wireshark for viewing:
10 2f 00 04 4d 51 54 54 05 c2 00 3c 05 11 00 00 01 2c 00 0e 6d 71 74 74 78 5f 30 63 36 36 38 64 30 64 00 05 61 64 6d 69 6e 00 06 70 75 62 6c 69 63
But this is a string of hexadecimal bytes that is not easy to understand unless they are converted into the following format:
Similarly, we also captured the CONNACK packet returned by the public MQTT server:
20 13 00 00 10 27 00 10 00 00 25 01 2a 01 29 01 22 ff ff 28 01
After parsing this string of packet data, we can see that the Reason Code of the CONNACK packet is 0, which means that the connection was successful. The multiple properties that follow provide a list of features supported by the server, such as the maximum packet size supported, whether to support retained messages, etc:
The above examples are to help everyone better understand the structure of MQTT Packets. In actual applications, you can directly view the packet details in Wireshark. Wireshark provides excellent support for MQTT. It directly lists the values of each field for us, without the need for us to analyze ourselves:
Of course, Wireshark has actually listed the values of each field in the packet for us. Through the following introduction to the structure of the CONNECT and CONNACK packets, combined with the packet capture results of Wireshark, you will quickly master these two packets:
CONNECT Packet Structure
Fixed Header
In the Fixed Header of the CONNECT packet, the Packet Type field located in the high 4 bits of the first byte must be 1 (0b0001), and the low 4 bits in the first byte must all be 0.
Therefore, the value of the first byte of the CONNECT packet must be 0x10. We can use this to determine whether a packet is a CONNECT packet.
Variable Header
The Variable Header of the CONNECT packet contains the following fields in order:
- Protocol Name: This is a UTF-8 encoded string used to indicate the protocol name. In MQTT, the first two bytes of the UTF-8 encoded string are uniformly used to indicate the length of the actual character data that follows. The protocol name is fixed as MQTT in MQTT 3.1.1 and MQTT 5.0, so the corresponding complete content in hexadecimal bytes is 00 04 4d 51 54 54, where 4d 51 54 54 is the ASCII value of the string MQTT The protocol name in the earliest MQTT 3.1 is MQIsdp, so it corresponds to 00 06 4d 51 49 73 64 70.
- Protocol Version: This is a single-byte length unsigned integer used to indicate the protocol version. Currently, there are only three possible values, 3 represents MQTT 3.1, 4 represents MQTT 3.1.1, and 5 represents MQTT 5.0.
- Connect Flags: Connection flags, have a length of only one byte, but contain several flags used to indicate connection behavior or whether certain fields exist in the Payload.
- User Name Flag: Used to indicate whether the Payload contains the Username.
- Password Flag: Used to indicate whether the Payload contains the Password.
- Will Retain: Used to indicate whether the will message is a retained message.
- Will QoS: Used to indicate the QoS of the will message.
- Will Flag: Used to indicate whether the Payload contains relevant fields of the will message.
- Clean Start: Used to indicate whether the current connection is a new session or a continuation of an existing session, which determines whether the server will directly create a new session or attempt to reuse an existing session.
-
Reserved: This is a reserved bit, its value must be 0.
- Keep Alive: This is a double-byte length unsigned integer used to indicate the maximum time interval between two adjacent control packets sent by the client.
- Properties: The table below lists all available properties of the CONNECT packet.
Payload
In the Payload of the CONNECT packet, aside from the Client ID, all other fields are optional. Their existence depends on the value of the corresponding flag in the Connect Flags of the variable header. However, if these exist, they must appear in the order of Client ID, Will Properties, Will Topic, Will Payload, User Name, and Password.
CONNACK Packet Structure
Fixed Header
The value of the high 4 bits in the first byte of the Fixed Header is 2 (0b0010), indicating that this is a CONNACK packet.
Variable Header
The Variable Header of the CONNACK packet contains the following fields in order:
-
Connect Acknowledge Flags: Connection confirmation flag.
- Reserved (Bit 7 - 1): Reserved bits, must be set to 0.
- Session Present (Bit 0): Used to indicate whether the server is using an existing session to resume communication with the client. Session Present may be 1 only when the client has set Clean Start to 0 in the CONNECT connection.
Reason Code: Used to indicate the result of the connection. The table below lists some common Reason Codes in the CONNACK packet, for a complete list, please refer to the MQTT 5.0 Reason Code Quick Reference Guide.
- Properties: The table below lists all available properties for the CONNACK packet.
IdentifierProperty NameType0x11Session Expiry IntervalFour Byte Integer0x21Receive MaximumTwo Byte Integer0x24Maximum QoSByte0x25Retain AvailableBytes0x27Maximum Packet SizeFour Byte Integer0x12Assigned Client IdentifierUTF-8 Encoded String0x22Topic Alias MaximumTwo Byte Integer0x1FReason StringUTF-8 Encoded String0x26User PropertyUTF-8 String Pair0x28Wildcard Subscription AvailableByte0x29Subscription Identifier AvailableBytes0x2AShared Subscription AvailableByte0x13Server Keep AliveTwo Byte Integer0x1AResponse InformationUTF-8 Encoded String0x1CServer ReferenceUTF-8 Encoded String0x15Authentication MethodUTF-8 Encoded String0x16Authentication DataBinary Data
Payload
The CONNACK packet has no Payload.
Conclusion
CONNECT is the first MQTT packet sent by the client after the network connection between the client and the server is established. CONNACK, as the response packet of CONNECT, indicates the connection result through the reason code.
The client and server need to use CONNECT and CONNACK packets to complete the exchange of necessary information, such as the protocol version, Client ID, user name, password used by the client, and the maximum packet size and QoS supported by the server, and whether there is a corresponding session.
The above is an introduction to the MQTT CONNECT and CONNACK packets. In subsequent articles, we will continue to study the structure and composition of packets like PUBLISH, and DISCONNECT.
Originally published at www.emqx.com