Note: All data values will be in little-endian order, that is,
lower order bytes preceed higher order bytes. A 16 bit word would be presented
on the wire as LSB, then MSB.
The only exception to this the length field of a UTF-encoded
string, which is defined by the standard to be network-ordered, i.e. big-endian.
A fixed length header will always be present for each message. The fixed length header will consist of 2 bytes containing the message Type, Flags, and one byte of the Remaining Length field.
The format of the fixed length header is as follows:
bit |
|
|
|
|
|
|
|
|
byte 1 |
|
|
|
|
||||
byte 2 |
|
The Message Type field is represented as a 4 bit unsigned value. The
enumerations of the Type field defined at this version of the protocol
are as follows:
Mnemonic | Enumeration | Description |
reserved |
|
Not used, but reserved |
CONNECT |
|
Client request to connect to Broker |
CONNACK |
|
Connect Acknowledgement |
PUBLISH |
|
Publish message |
PUBACK |
|
Publish Acknowledgement |
PUBREC |
|
Publish Received (assured delivery part 1) |
PUBREL |
|
Publish Release (assured delivery part 2) |
PUBCOMP |
|
Publish Complete (assured delivery part 3) |
SUBSCRIBE |
|
Client Subscribe request |
SUBACK |
|
Subscribe Acknowledgement |
UNSUBSCRIBE |
|
Client Unsubscribe request |
UNSUBACK |
|
Unsubscribe Acknowledgement |
PINGREQ |
|
PING Request |
PINGRESP |
|
PING Response |
DISCONNECT |
|
Client is Disconnecting |
reserved |
|
Reserved for future use |
Note that message type 0 is not a valid message code.
Bit position | Name | Description |
|
DUP | Duplicate delivery |
|
QoS | Quality of Service |
|
RETAIN | RETAIN flag |
The interpretation of these flags is as follows:
The DUP bit will be set any time the client or broker tries to deliver
a PUBLISH message that has already been sent. This only applies to messages
of QoS > 0 which require acknowledgement (see below). By definition, when
the DUP bit is set, the Variable Header
will include a Message Identifier.
The QoS bits are used to indicate the level of assurance of delivery
of a PUBLISH message. There are four possible values which can be represented
by the two QoS bits. The QoS levels are defined as follows:
QoS value | bit 2 | bit 1 | Descriptions | ||
|
0 | 0 | at most once | "Fire and Forget" | <=1 |
|
0 | 1 | at least once | "Acknowledged delivery" | >=1 |
|
1 | 0 | exactly once | "Assured delivery" | ==1 |
|
1 | 1 | not used |
The RETAIN flag is an indication to the broker that this message should be held, if possible, in the broker, and should be sent to any new subscriber to this Topic as an initial message. This allows a complete "current state" of a number of Topics to be quickly established by a new client upon connecting to the broker. This is particularly useful if publishers are only sending messages on a "Report By Exception" basis: it may be a very long time before a new subscriber receives any data on a particular Topic. The data is known as the "Retained", or "Last Known Good" (LKG) value.
After a SUBSCRIBE to one or more Topics, a subscriber will receive a SUBACK, and then one message for each of the newly subscribed Topics for which there is currently a Retained value. The Retained value is published from the broker to the subscriber with the RETAIN flag set, and with the same QoS with which it was originally published, and so will be subject to the usual QoS delivery assurances. The RETAIN flag is set in the message to the subscribers to distinguish it from "live" data, so that it can be handled appropriately by the subscriber.
Note that there is no guarantee that a previous Retained PUBLISH
to the broker will still be held by the broker, and so the subscriber might
not receive an initial Retained PUBLISH on a
Topic.
The Remaining Length field represents the number of bytes remaining
withing the current message, including data in the Variable
Header portion of the message, and the user-defined Payload.
The field is encoded using a variable-length scheme which allows the
use of just a single byte for message lengths up to 127 bytes, but which
also allows larger messages to be carried when required. The encoding scheme
is as follows:
Seven bits of each byte are used to encode the Remaining Length data, and the eighth bit in each byte is used to indicate whether or not there are any following bytes in the representation. Each byte thus encodes 128 values and a "continuation bit".
For example, the number 64 decimal is encoded as by a single byte, decimal
value 64, hex 0x40.
The number 321 decimal (=128x2 + 65) is encoded as two bytes, least
significant first:
First byte: 2+128 = 130 (note the top bit being set to indicate
there is at least one following byte)
Second byte: 65
This version of the protocol limits the number of bytes in the representation
to a maximum of four (4). This permits a single message of up to 268,435,455
(256MB) to be sent. It is felt that this will be more than adequate for
the foreseeable future.
The representation of this number on the wire would be 0xFF, 0xFF,
0xFF, 0x7F.
Using this encoding scheme, the Remaining Length values which can be
represented by increasing numbers of bytes is as follows:
digits | from | to |
|
0 (0x00) | 127 (0x7F) |
|
128 (0x80, 0x01) | 16,383 (0xFF, 0x7F) |
|
16,384 (0x80, 0x80, 0x01) | 2,097,151 (0xFF, 0xFF, 0x7F) |
|
2,097,152 (0x80, 0x80, 0x80, 0x01) | 268,435,455 (0xFF, 0xFF, 0xFF, 0x7F) |
The algorithm for encoding a decimal number into this format is quite straightforward, and looks like this:
X is the number to convert to variable length encoding scheme
dodigit = X MOD 128while ( X > 0 )
x = X DIV 128// if there are more digits to encode, set the top bit of this digit
if ( X > 0 )digit = digit OR 0x80endif'output' digit
Note: MOD is the modulo operator ('%' in C), DIV
is integer division ('/' in C), and OR is bit-wise or ('|' in
C).
The algorithm for decoding the Remaining Length field as it comes off
the wire is similarly straightforward:
multiplier = 1Note: AND is the bit-wise and operator ('&' in C).
value = 0do
digit = 'next digit from stream'while ((digit AND 128) != 0);value += (digit AND 127) * multiplier;
multiplier *= 128;
When this algorithm terminates, 'value' contains the Remaining Length in bytes.
Note that the Remaining Length encoding is not part of the Variable
Header portion of the message, and so the number of bytes taken to encode
the Remaining Length does not itself contribute to the value of the Remaining
Length. The "extension bytes" of the variable length encoding should therefore
be thought of as part of the Fixed Header, rather than part of the Variable
Header.
BACK to index