Connect MQTT Clients Using Paho C

Text Copied

Introduction

This guide helps you use the Eclipse Paho C client to connect to an MQTT broker, publish messages, and subscribe to topics. It's lightweight, written in C, and supports MQTT v3.1.1 and v5.0 — ideal for embedded and IoT applications.

Pre-requisites

Before you begin, ensure you have the following set up:

  • Eclipse Paho C library installed.
  • For Linux-based platforms
  • git clone --branch v1.3.14 https://github.com/eclipse/paho.mqtt.c.git
    cd paho.mqtt.c
    make
    sudo make install

  • For Windows
  • mkdir build.paho
    cd build.paho
    call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
    cmake -G "NMake Makefiles" -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=FALSE -DPAHO_BUILD_SAMPLES=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=TRUE ..
    nmake

Connecting to MQTT Broker

This section covers multiple ways to connect to an MQTT broker. Make sure you have the broker details (hostname, port, username/password, CA certificate) handy.

Basic TCP Connection

#define ADDRESS "tcp://public-mqtt-broker.bevywise.com:1883"
#define CLIENTID "testclient4"
MQTTAsync client;
MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}

Connect with Authentication

MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.username = "your-mqtt-username";
conn_opts.password = "your-mqtt-password";

Connect over TLS/SSL

MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
ssl_opts.verify = 0;ssl_opts.sslVersion = MQTT_SSL_VERSION_TLS_1_2;
ssl_opts.enableServerCertAuth = 1;
ssl_opts.verify = 1;
conn_opts.ssl = &ssl_opts;

Connect via WebSocket

#define ADDRESS
"ws://freemqttbroker.sfodo.mqttserver.com:10443"

MQTT Publish

#define TOPIC "device/status"
#define PAYLOAD "ON"
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = 1;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}

MQTT Subscribe

#define FILTER "your-topic-filter"
#define QOS 1
if ((rc = MQTTAsync_subscribe(client, FILTER, QOS, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to subscribe, return code %d\n", rc);
exit(EXIT_FAILURE);
}

To unsubscribe:

#define FILTER "your-topic-filter"
if ((rc = MQTTAsync_unsubscribe(client, FILTER, NULL)) != MQTTASYNC_SUCCESS)
{
printf("Failed to unsubscribe, return code %d\n", rc);
}

MQTT Disconnect

Clean disconnection ensures the broker releases resources tied to the session and avoids lingering socket connections.

MQTTAsync_disconnect(client, NULL);
MQTTAsync_destroy(&client);

Sample MQTTv311 Client


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "MQTTAsync.h"
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "testclientC4"
#define TOPIC "sensor/temperature"
#define PAYLOAD "180"
#define QOS 1
#define TIMEOUT 10000L
int AUTHENTICATION = 0;
int finished = 0;
void onDisconnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful disconnection\n");
    finished = 1;
}
void onSubscribe(void* context, MQTTAsync_successData* response)
{
    printf("Subscribe succeeded\n");
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
    printf("Connect failed, rc %d\n", response ? response->code : 0);
    finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful connection\n");
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
    int i;
    char* payloadptr;
    printf("Message arrived\n");
    printf(" topic: %s\n", topicName);
    printf(" message: ");
    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    MQTTAsync_freeMessage(&message);
    MQTTAsync_free(topicName);
    finished = 1;
    return 1;
}
int main(int argc, char* argv[])
{
    // Create Client
    MQTTAsync client;
    MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    MQTTAsync_setCallbacks(client, NULL, NULL, msgarrvd, NULL);
    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
    if (AUTHENTICATION == 1) 
    {
        conn_opts.username = "dev2";
        conn_opts.password = "key2";
    }
    conn_opts.keepAliveInterval = 60;
    conn_opts.cleansession = 1;
    conn_opts.onSuccess = onConnect;
    conn_opts.onFailure = onConnectFailure;
    conn_opts.context = client;
    int rc;
    if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to start connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    sleep(1);
    // Subscribe
    MQTTAsync_responseOptions sub_opts = MQTTAsync_responseOptions_initializer;
    sub_opts.onSuccess = onSubscribe;
    sub_opts.context = client;
    if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &sub_opts)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    // Publish
    MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
    pubmsg.payload = PAYLOAD;
    pubmsg.payloadlen = strlen(PAYLOAD);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
    if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, NULL)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to start sendMessage, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    while (!finished) 
    {
        #if defined(WIN32) || defined(WIN64)
        Sleep(100);
        #else
        usleep(10000L);
        #endif
    }
    MQTTAsync_destroy(&client);
    return rc;
}


Save the code as mqtt4Client.c

Compile:

gcc -o mqtt4client mqtt4Client.c -lpaho-mqtt3a -lpaho-mqtt3as


Execute:

./mqtt4client

Sample MQTTv5 Client


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "MQTTAsync.h"
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "testClientC5"
#define TOPIC "sensor/humidity"
#define PAYLOAD "20.3"
#define QOS 1
#define TIMEOUT 10000L
int AUTHENTICATION = 0;
int finished = 0;
void onDisconnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful disconnection\n");
    finished = 1;
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
    printf("Connect failed, rc %d\n", response ? response->code : 0);
    finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
    printf("Successful connection\n");
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
    int i;
    char* payloadptr;
    printf("Message arrived\n");
    printf(" topic: %s\n", topicName);
    printf(" message: ");
    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    MQTTAsync_freeMessage(&message);
    MQTTAsync_free(topicName);
    finished = 1;
    return 1;
}
int main(int argc, char* argv[])
{
    // Create Client
    MQTTAsync client;
    MQTTAsync_createOptions create_opts = MQTTAsync_createOptions_initializer;
    create_opts.MQTTVersion = MQTTVERSION_5;
    int rc = MQTTAsync_createWithOptions(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL, &create_opts);
    MQTTAsync_setCallbacks(client, NULL, NULL, msgarrvd, NULL);
    // Set CONNECT Properties
    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer5;
    if (AUTHENTICATION == 1) 
    {
        conn_opts.username = "dev2";
        conn_opts.password = "key2";
    }
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleanstart = 1;
    conn_opts.onSuccess = onConnect;
    conn_opts.onFailure = onConnectFailure;
    conn_opts.context = client;
    MQTTProperties props = MQTTProperties_initializer;
    // // Session Expiry Interval
    MQTTProperty property1;
    property1.identifier = MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL;
    property1.value.integer2 = 90;
    MQTTProperties_add(&props, &property1);
    conn_opts.connectProperties = &props;
    if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to start connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    sleep(1);
    // Subscribe
    if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, NULL)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    sleep(1);
    // Publish
    MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
    pubmsg.payload = PAYLOAD;
    pubmsg.payloadlen = strlen(PAYLOAD);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
    // Set Publish Properties
    MQTTAsync_responseOptions pub_opts = MQTTAsync_responseOptions_initializer;
    pub_opts.context = client;
    MQTTProperties pub_props = MQTTProperties_initializer;
    MQTTProperty property3;
    property3.identifier = MQTTPROPERTY_CODE_TOPIC_ALIAS;
    property3.value.integer4 = 90;
    MQTTProperties_add(&pub_props, &property3);
    pub_opts.properties = pub_props;
    if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &pub_opts)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to start sendMessage, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    sleep(1);
    if ((rc = MQTTAsync_unsubscribe(client, TOPIC, NULL)) != MQTTASYNC_SUCCESS)
    {
        printf("Failed to unsubscribe, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    while (!finished)
    {
        #if defined(WIN32) || defined(WIN64)
        Sleep(100);
        #else
        usleep(10000L);
        #endif
    }
    MQTTAsync_destroy(&client);
    return rc;
}


Save the code as mqtt5Client.c

Compile:

gcc -o mqtt5client mqtt5lient.c -lpaho-mqtt3a -lpaho-mqtt3as


Execute:

./mqtt5client

Troubleshooting

  • If the MQTT broker URL is wrong or not reachable, the program may throw a connection exception.
  • If you're using TLS, make sure to enable it and set port to 8883.

Scale IoT with C!

Enable Smarter Connectivity
for C Applications

Take control of your device communication with predictable, secure, and easy-to-manage MQTT messaging.