MQTT Essentials Part 4: MQTT Publish, Subscribe & Unsubscribe

MQTT Essentials Part 4 Banner

Welcome to the fourth part of the MQTT Essentials, a blog series about the core features and concepts in the MQTT protocol. In this post, we’ll focus on publish, subscribe and unsubscribe in MQTT. In contrast to the second part, which was about publish/subscribe basics, this post will explain the specifics of publish and subscribe in the MQTT protocol. If you haven’t read part 2 about the basics of the publish/subscribe pattern, we strongly encourage you to read it first.

Last week we looked at establishing a connection between MQTT client and broker. So this week’s post ties on to this and we’ll talk about sending and receiving messages.

Publish

After a MQTT client is connected to a broker, it can publish messages. MQTT has a topic-based filtering of the messages on the broker (check part 2 for more details on that), so each message must contain a topic, which will be used by the broker to forward the message to interested clients. Each message typically has a payload which contains the actual data to transmit in byte format. MQTT is data-agnostic and it totally depends on the use case how the payload is structured. It’s completely up to the sender if it wants to send binary data, textual data or even full-fledged XML or JSON. A MQTT publish message also has some more attributes, which we’re going discuss in detail:

MQTT Publish attributes

Topic Name
A simple string, which is hierarchically structured with forward slashes as delimiters. An example would be “myhome/livingroom/temperature” or “Germany/Munich/Octoberfest/people”. More details about topics can be found in part 5 of the MQTT Essentials.

QoS
A Quality of Service Level (QoS) for this message. The level (0,1 or 2) determines the guarantee of a message reaching the other end (client or broker). More details about QoS can be found in part 6 of the MQTT Essentials.

Retain-Flag
This flag determines if the message will be saved by the broker for the specified topic as last known good value. New clients that subscribe to that topic will receive the last retained message on that topic instantly after subscribing. More on retained messages and best practices in one of the next posts.

Payload
This is the actual content of the message. MQTT is totally data-agnostic, it’s possible to send images, texts in any encoding, encrypted data and virtually every data in binary.

Packet Identifier
The packet identifier is a unique identifier between client and broker to identify a message in a message flow. This is only relevant for QoS greater than zero. Setting this MQTT internal identifier is the responsibility of the client library and/or the broker.

DUP flag
The duplicate flag indicates, that this message is a duplicate and is resent because the other end didn’t acknowledge the original message. This is only relevant for QoS greater than 0 and more details are in part 6, which is about QoS levels. This resend/duplicate mechanism is typically handled by the MQTT client library or the broker as an implementation detail.

So when a client sends a publish to a MQTT broker, the broker will read the publish, acknowledge the publish if needed (according to the QoS Level) and then process it. Processing includes determining which clients have subscribed on that topic and then sending out the message to the selected clients which subscribe to that topic.

MQTT Publish Message Flow

The client, who initially published the message is only concerned about delivering the publish message to the broker. From there on it is the responsibility of the broker to deliver the message to all subscribers. The publishing client doesn’t get any feedback, if someone was interested in this published message and how many clients received the message by the broker.

Subscribe

Publishing messages doesn’t make sense if no one ever receives the message, or, in other words, if there are no clients subscribing to any topic. A client needs to send a SUBSCRIBE message to the MQTT broker in order to receive relevant messages. A subscribe message is pretty simple, it just contains a unique packet identifier and a list of subscriptions.

MQTT Subscribe attributes

Packet Identifier
The packet identifier is a unique identifier between client and broker to identify a message in a message flow. This is only relevant for QoS greater than zero. Setting this MQTT internal identifier is the responsibility of the client library and/or the broker.

List of Subscriptions
A SUBSCRIBE message can contain an arbitrary number of subscriptions for a client. Each subscription is a pair of a topic topic and QoS level. The topic in the subscribe message can also contain wildcards, which makes it possible to subscribe to certain topic patterns. If there are overlapping subscriptions for one client, the highest QoS level for that topic wins and will be used by the broker for delivering the message.

Suback

Each subscription will be confirmed by the broker through sending an acknowledgment to the client in form of the SUBACK message. This message contains the same packet identifier as the original Subscribe message (in order to identify the message) and a list of return codes.

MQTT SUBACK attributes

Packet Identifier
The packet identifier is a unique identifier used to identify a message. It is the same as in the SUBSCRIBE message.

Return Code
The broker sends one return code for each topic/QoS-pair it received in the SUBSCRIBE message. So if the SUBSCRIBE message had 5 subscriptions, there will be 5 return codes to acknowledge each topic with the QoS level granted by the broker. If the subscription was prohibited by the broker (e.g. if the client was not allowed to subscribe to this topic due to insufficient permission or if the topic was malformed), the broker will respond with a failure return code for that specific topic.

Return CodeReturn Code Response
0Success – Maximum QoS 0
1Success – Maximum QoS 1
2Success – Maximum QoS 2
128Failure

MQTT Subscribe Flow

After a client successfully sent the SUBSCRIBE message and received the SUBACK message, it will receive every published message matching the topic of the subscription.

Unsubscribe

The counterpart of the SUBSCRIBE message is the UNSUBSCRIBE message which deletes existing subscriptions of a client on the broker. The UNSUBSCRIBE message is similar to the SUBSCRIBE message and also has a packet identifier and a list of topics.

MQTT Unsubscribe attributes

Packet Identifier
The packet identifier is a unique identifier used to identify a message. The acknowledgement of an UNSUBSCRIBE message will contain the same identifier.

List of Topic
The list of topics contains an arbitrary number of topics, the client wishes to unsubscribe from. It is only necessary to send the topic as string (without QoS), the topic will be unsubscribed regardless of the QoS level it was initially subscribed with.

Unsuback

The broker will acknowledge the request to unsubscribe with the UNSUBACK message. This message only contains a packet identifier.

MQTT UNSUBACK attributes

Packet Identifier
The packet identifier is a unique identifier used to identify a message. It is the same as in the UNSUBSCRIBE message.

Unsubscribe Flow

After receiving the UNSUBACK from the broker, the client can assume the subscriptions in the UNSUBSCRIBE message are deleted.


So that’s the end of part four in our MQTT Essentials series. We hope you enjoyed it. In the next post we will dig deeper into the usage of MQTT topics. We’ll explain the basics as well as the usage of wildcards and a lot of practical examples.

Have a great week and we’ll hope to see you on the next MQTT Monday!

If you still haven’t signed up for our newsletter in order to get each new post delivered directly to your inbox, you can do so below. If you prefer RSS, you can subscribe to our RSS feed here.

18 comments

  1. Guy Avraham says:

    Hi there,

    Correct me if I’m mistaken , but in the example of the SUBSCRIBE/SUBACK messages , isn’t the packetId filed should be the same (therefor , in the SUBACK message , it should be modified to the value of the corresponding SUBSCRIBE message , which is 4312) ?

    Other than that , these tutorials are great !!
    Great work guys !!

    Thanks,
    Guy.

    1. Hi Guy,

      thanks so much for the feedback. Your are right, it seems there is indeed an error in the picture. Nice catch! :-)

      All the best,
      Dominik from the HiveMQ Team

  2. Nena says:

    Is it bad practice to send an unsolicited message to an MQTT client? Ie, the client has not subscribed to a particular topic, but the broker sends a message to the client anyways? Example, in the event of an error?

    1. Hi Nena,

      it is possible with HiveMQ’s plugin system to do this, but it is bad practice since the client might not expect to receive a message on a topic it is not subscribed to.

      Hope that helps,
      Christoph from the HiveMQ Team

  3. triawan says:

    hi, what is the meaning of this “received PUBLISH (d0, q0, r0, m0, ‘get/123’, … (70 bytes))” ?

    1. Hi triawan,

      the fields have the following meaning:
      d0 => duplicate flag: false
      q0 => QoS: 0
      r0 => retained: false
      m0 => messageID: 0

      Hope that helps,
      Christoph from the HiveMQ Team

    2. sanlie says:

      it trace string for :
      dup flag = false, qos = 0 (atMostOnce), retained = false, mesageId = 0, topic: ‘get/123’, 70 bytes: packet length from PUBLISH message

  4. Phuoc Thua says:

    Hi,

    I have tried to assign a struct into payload (using Paho client, convert to void* before assigning). I published success, the subscriber can received it. But when I converted the payload from void* to struct to use I got segmentaion fault (core dumped). So can the payload only point to a char array (or it can only be “the actual content of the message” as the article) ?

    Thanks,
    Phuoc Thua.

    1. Charles says:

      Hi Phuoc,

      You probably need to serialize your structure into a sequential byte array, and then send that as message payload.
      On the receiving end, you need to deserialize the byte array into your structure.

      Hope this helps,
      Charles

  5. Kamala Kris says:

    In SUBSCRIBE example figure the topic 2 should be topic/2 and not topic/1. Correct me if I am wrong.

    1. Hi Kamala,

      good catch! The topic2 should indeed be “topic/2”.

      Thanks and all the best,
      Dominik from the HiveMQ Team

  6. Sudeep Nayak says:

    Hi,

    I’m working on sharing images and videos using Mqtt. I want to know if the total transfer time depends on the number of clients receiving the file? And also, which encoding scheme works fastest to transfer images/video?

    Thanks.

    1. Hi Sudeep,

      I’m not sure what you mean with total transfer time. I’m assuming you mean end-to-end latency. You can check out the benchmarks here for some numbers: http://www.hivemq.com/benchmarks/

      Best,
      Dominik from the HiveMQ Team

  7. Chase says:

    First, thanks for this really fantastic series. I have a small (maybe picky) but I think important suggestion.

    Under the “DUP flag” subheading you state:

    “So when a client sends a publish to a MQTT broker…”

    It’s my understanding that clients don’t publish anything TO the broker but instead just publish. Although this seems nit-picky, as a complete MQTT beginner, it is a point of confusion for me. I think correctly understanding the structure of the MQTT ecosystem is absolutely essential before diving into understanding how to use it. The fact that clients are just publishing, and that it’s the broker that controls “grabbing” (subscribing) to the data that is flying around… is a really important thing to understand correctly.

    Now, if I’m wrong about this point PLEASE correct me, as it will help me, and others, move forward in learning MQTT.

    Thanks again for this series and your dedication to responding to the comments!

    -Chase

    1. Hallo Chase,

      this is a good question. Let me try to clarify as simple as possible.
      if you look into the message flow of a MQTT message from the publisher to the subscriber, the following happens.

      Let’s assume we have ClientA publishing on topic: “anytopic” and we have ClientB subscribing on “anytopic”
      ClientA will publish the message “Some Payload” with the topic to HiveMQ.
      Now HiveMQ will check, which clients have subscriptions on that topic and will publish the message to those clients, in this case ClientB.

      Note that this is a simplified view and many MQTT specific mechanisms like QoS have not been considered.

      I hope this helps.

      Florian, from the HiveMQ Team.

  8. Axel says:

    Dear HiveMQ Team,

    Thank you very much for this great tutorial! Made my first mqtt steps much easier.

    Please allow me a question: I played with different Clients (also with your web Client) but I had always the effect that when I publish an identical message twice (QOS=0, retain=true) then my subsriber receives two messages. I expected that I receive the first message only. And after that only changes of the message will be received.
    Is my understanding or my configuration of the Publisher wrong.

    Thank you very much in advance.
    Best Regards
    Axel

    1. Hallo Axel,

      Glad to see you like our content and it helped you get started with MQTT.

      Regarding your question:
      Unfortunately your understanding of retained messages is indeed incorrect. One retained message for a specific topic (The last message published on the topic, regardless of the payload) can be stored by the broker so that any new subscribers on that specific topic will be able to get that message. This does not in any way influence the message flow of currently connected subscribers.
      See this post from this series for further information.

      I hope that was helpful.
      Best regards,
      Florian, from the HiveMQ Team.

Leave a Reply

Your email address will not be published. Required fields are marked *