subscribe(3)

🌸 NAME 🌸

subscribe β€” Subscription example πŸ’–

okay bestie, gather round, because this is the manual page for subscribe(3) from the Library Functions Manual and it is literally a whole working example of how you subscribe to an MQTT topic with the Paho asynchronous C client. no cap. it's giving "here's the entire program, go off". πŸ‘‘


πŸ¦‹ the setup stuff πŸ¦‹

first we pull in the headers, and there's some platform drama because Windows and everything-else do not vibe the same way:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTAsync.h"

#if !defined(_WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif

#if defined(_WRS_KERNEL)
#include <OsWrapper.h>
#endif

then the constants, which are lowkey the whole personality of this example:

#define ADDRESS     "tcp://test.mosquitto.org:1883"
#define CLIENTID    "ExampleClientSub"
#define TOPIC       "MQTT Examples"
#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000L

ADDRESS is where the broker lives, CLIENTID is who we are, TOPIC is what we're stalking, PAYLOAD is the message we love, QOS is 1, and TIMEOUT is 10000L. periodt. πŸ’…


✨ the state flags ✨

three little ints, doing the absolute most:

int disc_finished = 0;
int subscribed = 0;
int finished = 0;

disc_finished, subscribed, finished β€” all starting at 0, all eventually becoming someone's problem. 🫢


πŸ’€ when the connection ghosts you: connlost πŸ’€

void connlost(void *context, char *cause)
{
        MQTTAsync client = (MQTTAsync)context;
        MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
        int rc;

        printf("\nConnection lost\n");
        if (cause)
                printf("     cause: %s\n", cause);

        printf("Reconnecting\n");
        conn_opts.keepAliveInterval = 20;
        conn_opts.cleansession = 1;
        if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
        {
                printf("Failed to start connect, return code %d\n", rc);
                finished = 1;
        }
}

the vibe check failed, connection is GONE 😭. it prints "\nConnection lost\n", and if there's a cause it prints " cause: %s\n" with it. then it says "Reconnecting\n", sets conn_opts.keepAliveInterval = 20 and conn_opts.cleansession = 1, and calls MQTTAsync_connect(client, &conn_opts). if that's not MQTTASYNC_SUCCESS, it prints "Failed to start connect, return code %d\n" and sets finished = 1. iconic resilience honestly.


πŸ’– message arrived!! msgarrvd πŸ’–

int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
    MQTTAsync_freeMessage(&message);
    MQTTAsync_free(topicName);
    return 1;
}

NOT ME GETTING A MESSAGE πŸŽ€ it prints "Message arrived\n", then " topic: %s\n" with topicName, then " message: %.*s\n" using message->payloadlen and (char*)message->payload. then it cleans up after itself with MQTTAsync_freeMessage(&message) and MQTTAsync_free(topicName) because we are a tidy queen, and returns 1. πŸ‘‘


🌈 the callback girlies 🌈

void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
        printf("Disconnect failed, rc %d\n", response->code);
        disc_finished = 1;
}

void onDisconnect(void* context, MQTTAsync_successData* response)
{
        printf("Successful disconnection\n");
        disc_finished = 1;
}

void onSubscribe(void* context, MQTTAsync_successData* response)
{
        printf("Subscribe succeeded\n");
        subscribed = 1;
}

void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
        printf("Subscribe failed, rc %d\n", response->code);
        finished = 1;
}

void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
        printf("Connect failed, rc %d\n", response->code);
        finished = 1;
}

let's break it down bestie:

  • onDisconnectFailure β€” prints "Disconnect failed, rc %d\n" with response->code, sets disc_finished = 1. πŸ™ˆ
  • onDisconnect β€” prints "Successful disconnection\n", sets disc_finished = 1. clean exit energy.
  • onSubscribe β€” prints "Subscribe succeeded\n", sets subscribed = 1. ATE. πŸ”₯
  • onSubscribeFailure β€” prints "Subscribe failed, rc %d\n" with response->code, sets finished = 1.
  • onConnectFailure β€” prints "Connect failed, rc %d\n" with response->code, sets finished = 1.

five callbacks, zero notes, all slay. ✨


🧚 onConnect β€” the main character 🧚

void onConnect(void* context, MQTTAsync_successData* response)
{
        MQTTAsync client = (MQTTAsync)context;
        MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
        int rc;

        printf("Successful connection\n");

        printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
        opts.onSuccess = onSubscribe;
        opts.onFailure = onSubscribeFailure;
        opts.context = client;
        if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
        {
                printf("Failed to start subscribe, return code %d\n", rc);
                finished = 1;
        }
}

we made it, we're connected 🫢 it prints "Successful connection\n", then the big announcement: "Subscribing to topic %s\nfor client %s using QoS%d\n\n" and "Press Q<Enter> to quit\n\n", filled in with TOPIC, CLIENTID and QOS. then it wires up opts.onSuccess = onSubscribe, opts.onFailure = onSubscribeFailure, opts.context = client, and fires MQTTAsync_subscribe(client, TOPIC, QOS, &opts). if that doesn't return MQTTASYNC_SUCCESS it prints "Failed to start subscribe, return code %d\n" and sets finished = 1. the way this function just does everything. πŸ’…


πŸ‘‘ main β€” the whole plot πŸ‘‘

int main(int argc, char* argv[])
{
        MQTTAsync client;
        MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
        MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
        int rc;
        int ch;

        if ((rc = MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL))
                        != MQTTASYNC_SUCCESS)
        {
                printf("Failed to create client, return code %d\n", rc);
                rc = EXIT_FAILURE;
                goto exit;
        }

        if ((rc = MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL)) != MQTTASYNC_SUCCESS)
        {
                printf("Failed to set callbacks, return code %d\n", rc);
                rc = EXIT_FAILURE;
                goto destroy_exit;
        }

        conn_opts.keepAliveInterval = 20;
        conn_opts.cleansession = 1;
        conn_opts.onSuccess = onConnect;
        conn_opts.onFailure = onConnectFailure;
        conn_opts.context = client;
        if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
        {
                printf("Failed to start connect, return code %d\n", rc);
                rc = EXIT_FAILURE;
                goto destroy_exit;
        }

        while (!subscribed && !finished)
                #if defined(_WIN32)
                        Sleep(100);
                #else
                        usleep(10000L);
                #endif

        if (finished)
                goto exit;

        do
        {
                ch = getchar();
        } while (ch!='Q' && ch != 'q');

        disc_opts.onSuccess = onDisconnect;
        disc_opts.onFailure = onDisconnectFailure;
        if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
        {
                printf("Failed to start disconnect, return code %d\n", rc);
                rc = EXIT_FAILURE;
                goto destroy_exit;
        }
        while (!disc_finished)
        {
                #if defined(_WIN32)
                        Sleep(100);
                #else
                        usleep(10000L);
                #endif
        }

destroy_exit:
        MQTTAsync_destroy(&client);
exit:
        return rc;
}

the step-by-step, because i love a structured queen:

  1. MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) β€” if it's not MQTTASYNC_SUCCESS, print "Failed to create client, return code %d\n", set rc = EXIT_FAILURE, and goto exit.
  2. MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL) β€” fail? print "Failed to set callbacks, return code %d\n", rc = EXIT_FAILURE, goto destroy_exit.
  3. set conn_opts.keepAliveInterval = 20, conn_opts.cleansession = 1, conn_opts.onSuccess = onConnect, conn_opts.onFailure = onConnectFailure, conn_opts.context = client, then MQTTAsync_connect(client, &conn_opts) β€” fail? print "Failed to start connect, return code %d\n", rc = EXIT_FAILURE, goto destroy_exit.
  4. spin: while (!subscribed && !finished) with Sleep(100) on _WIN32 or usleep(10000L) otherwise. (note: while with a preprocessor conditional as its body β€” iykyk. πŸ’€)
  5. if (finished) goto exit;
  6. wait for input: do { ch = getchar(); } while (ch!='Q' && ch != 'q'); β€” yes bestie, you literally type Q or q to quit. that's the exit interview.
  7. set disc_opts.onSuccess = onDisconnect, disc_opts.onFailure = onDisconnectFailure, then MQTTAsync_disconnect(client, &disc_opts) β€” fail? print "Failed to start disconnect, return code %d\n", rc = EXIT_FAILURE, goto destroy_exit.
  8. while (!disc_finished) and again Sleep(100) on _WIN32, usleep(10000L) otherwise.
  9. destroy_exit: β†’ MQTTAsync_destroy(&client); then exit: β†’ return rc;

no extra options, no environment variables, no files, no exit-status table beyond that rc β€” this page is just the code, and we respect it for that. πŸ“

heads up: this page is a usage example, not a spec, so everything you need to understand it is right there in the source above. if you wanna actually understand the API, read it line by line β€” don't skim and guess, bestie. πŸ™ˆ

that's the whole thing, start to finish, no skips πŸ’œ the page came from the Paho Asynchronous MQTT C library documentation, dated Tue Jun 2 2026 00:00:00, and it's filed under subscribe(3). go write something iconic with it. mwah. πŸ’…πŸŽ€

πŸ“¦ where this page comes from