在 ARM 嵌入式 Linux 下使用 C/C++ 实现 MQTT

在 ARM 嵌入式 Linux 下使用 C/C++ 实现 MQTT 通信是一个常见的需求,尤其是在资源受限的环境中。以下是一个详细的教程,使用 Eclipse Paho C Client 库来实现 MQTT 客户端。


1. 安装 Eclipse Paho C Client 库

Eclipse Paho C Client 是一个轻量级的 MQTT 客户端库,适合嵌入式系统。

安装依赖

在 ARM 嵌入式 Linux 中,首先安装必要的依赖:

复制代码
sudo apt update
sudo apt install build-essential cmake libssl-dev
下载和编译 Paho C Client
  1. 下载 Paho C Client 源码:

    复制代码
    git clone https://github.com/eclipse/paho.mqtt.c.git
    cd paho.mqtt.c
  2. 编译并安装:

    复制代码
    cmake -Bbuild -H. -DPAHO_WITH_SSL=OFF
    make -C build
    sudo make -C build install

2. 编写 MQTT 客户端代码

以下是一个简单的 MQTT 客户端示例,包括订阅和发布功能。

代码:mqtt_client.c
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"

#define ADDRESS     "tcp://localhost:1883"
#define CLIENTID    "arm_mqtt_client"
#define TOPIC       "test/topic"
#define PAYLOAD     "Hello from ARM MQTT Client!"
#define QOS         1
#define TIMEOUT     10000L

// 收到消息的回调函数
void messageArrived(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
    printf("Message arrived on topic: %s\n", topicName);
    printf("Payload: %.*s\n", message->payloadlen, (char *)message->payload);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
}

int main() {
    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;

    // 创建 MQTT 客户端
    rc = MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to create client, return code: %d\n", rc);
        exit(EXIT_FAILURE);
    }

    // 设置消息到达回调
    rc = MQTTClient_setCallbacks(client, NULL, NULL, messageArrived, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to set callbacks, return code: %d\n", rc);
        MQTTClient_destroy(&client);
        exit(EXIT_FAILURE);
    }

    // 连接 MQTT 代理
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    rc = MQTTClient_connect(client, &conn_opts);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to connect, return code: %d\n", rc);
        MQTTClient_destroy(&client);
        exit(EXIT_FAILURE);
    }

    // 订阅主题
    rc = MQTTClient_subscribe(client, TOPIC, QOS);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to subscribe, return code: %d\n", rc);
        MQTTClient_disconnect(client, TIMEOUT);
        MQTTClient_destroy(&client);
        exit(EXIT_FAILURE);
    }
    printf("Subscribed to topic: %s\n", TOPIC);

    // 发布消息
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    pubmsg.payload = (void *)PAYLOAD;
    pubmsg.payloadlen = strlen(PAYLOAD);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
    rc = MQTTClient_publishMessage(client, TOPIC, &pubmsg, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("Failed to publish message, return code: %d\n", rc);
        MQTTClient_disconnect(client, TIMEOUT);
        MQTTClient_destroy(&client);
        exit(EXIT_FAILURE);
    }
    printf("Published message: %s\n", PAYLOAD);

    // 等待消息到达
    printf("Waiting for messages...\n");
    while (1) {
        sleep(1);
    }

    // 断开连接并销毁客户端
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
    return 0;
}

3. 编译代码

在 ARM 嵌入式 Linux 中编译代码:

复制代码
gcc -o mqtt_client mqtt_client.c -lpaho-mqtt3c

4. 运行代码

  1. 确保 Mosquitto 代理已启动。

  2. 运行编译后的程序:

    复制代码
    ./mqtt_client
  3. 如果一切正常,程序将订阅 test/topic 主题并发布一条消息。


5. 测试和验证

  1. 使用 mosquitto_sub 订阅 test/topic 主题:

    复制代码
    mosquitto_sub -h localhost -t test/topic
  2. 运行 mqtt_client,你应该能在 mosquitto_sub 终端中看到发布的消息。


6. 优化和注意事项

  1. 资源优化
    • 如果内存资源紧张,可以禁用 SSL(如示例中所示)。
    • 减少 MQTTClient_message 的缓冲区大小。
  2. 网络稳定性
    • 在嵌入式系统中,确保网络连接稳定,避免因网络问题导致通信失败。
  3. 日志管理
    • 在发布版本中禁用调试日志,减少资源占用。
  4. 交叉编译
    • 如果需要在开发主机上交叉编译,请使用合适的交叉编译工具链,例如:

      复制代码
      arm-linux-gnueabihf-gcc -o mqtt_client mqtt_client.c -lpaho-mqtt3c

通过以上步骤,可在 ARM 嵌入式 Linux 中成功实现 MQTT 通信,并编写高效的 C/C++ 客户端程序。

相关推荐
A小辣椒4 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒8 小时前
TShark:基础知识
linux
AlfredZhao10 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334661 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux