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. 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.

33 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.

  9. Ashutosh says:

    Dear HiveMQ Team,

    Thanks for this in-depth knowledge series for MQYY, its really simplistic approach to guide the MQTT basics.

    I am stuck at understanding one sentence from Publish section –
    “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.”

    My understading is publishing client doesnt get any feedback if someone is NOT interested in published message means no one has subscribed to that topic. Is it correct?

    Also didnt get context of – how many clients received the message by the broker.

    Will you please put some more light on it?

    Thanks,

    Ashutosh

    1. Hallo Ashutosh,

      Thank you for the kind words.
      I believe you’re understanding is already correct. What is meant by this sentence is very simple.
      The publisher doesn’t get any feedback about the subscribers, nor does he get feedback, when any of the subscribers actually receive the message.

      I hope this clarifies things. Let me know if you have a follow up question.
      Kind regards,
      Florian, from The HiveMQ Team.

  10. Susanna says:

    Dear HiveMQ Team,
    thanks for the great work on creating these very nice tutorials! as a very beginner with MQTT, I have a (probably trivial) question: is it possible that an MQTT client is at the same time both publisher and subscriber of a topic? If yes, does it mean that the message published by that client on that specific topic gets back to the same client, that is also a subscriber of that topic?
    thanks a lot,
    Susanna

    1. Hallo Susanna,

      Thank you for the kind words, we’re glad to see you are taking an interest in MQTT.
      In short: It is absolutely possible for a client to be both Publisher and Subscriber. As long as you do not subscribe on the topic, you are publishing on, the broker will not send the message back to your client.

      Kind regards,
      Florian from The HiveMQ Team.

  11. Shahzad says:

    Great tutorials!
    The post states **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**.

    I wonder if MQTT works on binary payload, than how subscribers will know that what type of data they are receiving (may be some one published a JSON, XML or even an image on the same topic). Is there anything like content-type as in HTTP which can tell what type of payload is?
    Thanks a lot.

    1. Hallo Sahzad,

      Glad you like the tutorial. You bring up a good question and almost answered it yourself already.
      The solution is to have dedicated topics for specific content types. A flag like in HTTP does not exist.

      Kind regards,
      Florian

  12. Hiren R Kanetiya says:

    How can i set a multiple Subscribe with different topic in particularly for ios objective C ? Please help me…
    i have set like this :
    [objCocoaMQTT subscribe:@”customToRM” qos:1];
    [objCocoaMQTT subscribe:@”approvedTopic” qos:2];
    IS it correct or not ? How can i check this would be setting the two different topic ? in code and as well as on debug log

    1. Hi there,

      Glad to see you’re taking an interest in MQTT. This blogpost shows the use of the objective C project for IoS.
      For more detailed information on the project please refer to the Github Page

      Kind regards,
      Florian from the HiveMQ Team.

  13. Christopher Maynard says:

    For the description of Packet Identifier under Subscribe, it is mentioned that, “This is only relevant for QoS greater than zero.” Isn’t that only true of the Publish messages? My understanding after reading section 2.3.1, and specifically Table 2.5 of MQTT Version 3.1.1, as well as section 3.8.2, is that the Packet Identifier is required for the Subscribe message, regardless of QoS.

    1. Hi Christopher,

      You are making an excellent point. The packet identifier is relevant for any MQTT message, that needs to be acknowledged.
      So besides PUBLISH greater than zero this is true for any SUBSCRIBE, UNSUBSCRIBE and CONNECT message.
      Thank you for pointing this out, I will adjust the post accordingly.

      Kind regards,
      Florian from the HiveMQ Team.

  14. NuB2Hive says:

    Hi, Wonderful tutorial!

    Q: Can a Client Subscribe to a Topic before any message on that topic has been published? Assume HiveMQ eventually flushed subscriptions like this that time out?

    Thx

    1. Hi there,

      Glad you are taking and interest in MQTT and that you like the tutorial.
      Regarding your question:
      Yes, you can absolutely subscribe to a topic no message has been published on yet.
      Not sure what you are asking on your second question. I will try to answer regardless.
      When taking advantage of the cleanSession=false option for your connection, HiveMQ will store the subscription even after a client times out.
      Otherwise the subscription will be removed, once the client disconnects.
      You can see this post for more information on that.
      Kind regards,
      Florian from the HiveMQ Team.

  15. NuB2Hive says:

    Thanks Florian you answered the second question too.

  16. saikiran says:

    Firstly, thanks for the wonderful information.

    I have a query. Please clarify!
    In case a client has sent an Unsubscribe request to broker. Lets say if some of the topics doesn’t exists at all. So in that case how would what will happen (since UnsubAck doesn’t have specific topics mentioned and just the message id, what will happen?)

    1. Hi there,

      Glad you like the information.
      When you unsubscribe from a topic the broker will acknowledge the UNSUBSCRIBE and remove the subscription for that clientID. If there was no subscription for that clientID on that topic nothing will happen. At the end of an unsubscribe, regardless of there being a subscription on that topic in place or not, the client will no longer be subscribed to the topic.

      I hope this answers your questions.

      Kind regards,
      Florian from The HiveMQ Team.

Leave a Reply

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