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.
Before you begin, ensure you have the following set up:
git clone --branch v1.3.14 https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c
make
sudo make install
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
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"
#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);
}
#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);
}
Clean disconnection ensures the broker releases resources tied to the session and avoids lingering socket connections.
MQTTAsync_disconnect(client, NULL);
MQTTAsync_destroy(&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
#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