在 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++ 客户端程序。

相关推荐
xiangw@GZ15 小时前
WiFi 全世代(WiFi1~WiFi7)技术规范与核心参数总结
嵌入式硬件
振南的单片机世界15 小时前
CPU时钟:频率越高跑越快,但物理极限在“拖后腿”
stm32·单片机·嵌入式硬件
fengyehongWorld15 小时前
TeraTerm ttl脚本登录wsl
linux·teraterm
乌托邦的逃亡者15 小时前
Linux中如何检测IP冲突
linux·运维·tcp/ip
一曦的后花园15 小时前
linux搭建promethes并对接node-exporter指标
linux·运维·服务器
普中科技16 小时前
【普中 51-Ai8051 开发攻略】-- 第 20 章 输入捕获实验
单片机·嵌入式硬件·输入捕获·pca·普中科技·ai8051u·aicube
d111111111d16 小时前
直流电机位置式 PID 控制 和 舵机的区别
笔记·stm32·单片机·嵌入式硬件·学习
乌托邦的逃亡者16 小时前
CentOS/Openeuler主机中,为一个网卡设置多个IP地址
linux·运维·网络·tcp/ip·centos
桌面运维家17 小时前
服务器进程异常监控:快速定位与排障实战指南
运维·服务器
@CLoudbays_Martin1117 小时前
UniApp是否能够接入SDK游戏盾呢?
服务器·网络·网络协议·tcp/ip·安全