C++接入MQTT

MQTT介绍

  MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。

  MQTT (Message Queuing Telemetry Transport) 是一种轻量级的消息传输协议,通常用于物联网设备和应用程序之间进行通信。它是基于发布/订阅模式设计的,其中消息发布者将消息发布到特定主题(Topic),然后订阅该主题的客户端将收到这些消息。MQTT 特别适合在网络带宽有限的情况下进行通信,因为它使用的数据包非常小。此外,它还提供了多种 QoS (Quality of Service) 级别来确保消息的可靠性和有效性。

MQTT 协议具有以下特点:

  • 轻量级:相对于 HTTP 等协议,MQTT 的数据包非常小,因此能够以较低的网络带宽进行通信。
  • 发布/订阅模式:通过订阅一个特定的主题,客户端能够接收和处理与该主题相关的所有消息。
  • 多种 QoS 级别:MQTT 提供了三种不同的 QoS级别,以满足不同场景下的需求。
  • 可扩展性:MQTT 的设计使得它能够方便地扩展到大规模系统中,并支持多种不同的连接方式,例如TCP、WebSocket 等。

  MQTT 支持三种不同级别的消息质量(Quality of Service,QoS),分别为 QoS0、QoS1 和 QoS2。

  • QoS0:最多发送一次,消息发送者只会将消息发布出去,但是并不保证接收者是否成功接收到该消息。这是最低级别的服务质量,也是最简单和最快速的传输方式。
  • QoS1:至少发送一次,消息发送者确保至少将消息传输给接收者一次。如果接收者没有确认消息或者确认消息失败,则消息发送者会尝试重新发送,直到接收者成功地接收到消息为止。
  • QoS2:恰好发送一次,消息发送者确保接收者恰好只能收到一次消息。在该级别下,消息发送者和接收者会进行两轮握手确认,以保证消息的可靠性和有效性。

  选择哪种服务质量级别取决于应用场景和对通信安全性的要求。需要注意的是,在选择高级别的服务质量时,会增加通信延迟和网络带宽的消耗。

  • 固定头(Fixed header),存在于所有MQTT数据包中,表示数据包类型及数据包的分组类标识;
  • 可变头(Variable header),存在于部分MQTT数据包中,数据包类型决定了可变头是否存在及其具体内容;
  • 消息体(Payload),存在于部分MQTT数据包中,表示客户端收到的具体内容;

MQTT(Mosquitto)安装与测试

  目前mqtt的代理平台主要有:Mosquitto、VerneMQ、EMQTT。

  下面在Ubuntu安装Mosquitto来体验mqtt的消息传递过程:

# 安装
sudo apt install mosquitto				# 服务端
sudo apt install mosquitto-clients		# 客户端

# 启动/关闭mqtt服务
mosquitto -v							# 启用所有日志记录类型
sudo service mosquitto start			# 启动
sudo service mosquitto stop				# 关闭
sudo systemctl status mosquitto			# 查看运行状态
mosquitto --help						# 查看帮助
ps -aux | grep mosquitto				# 查看运行进程号
kill -15 pid							# 执行命令杀死进程

# 消息传输测试
1、启动代理服务:mosquitto -v
   -v 详细模式 打印调试信息(启动一次就好)
2、订阅主题:mosquitto_sub -v -t hello
  -t 指定订阅的主题,主题为:hello
  -v 详细模式 打印调试信息
3、发布内容:mosquitto_pub -t hello -m world
  -t 指定订阅的主题,主题为:hello
  -m 指定发布的消息的内容

  此外,还可以去官网(https://mosquitto.org/)安装最新版源码并编译,编译后的版本适合用于开发。

  MQTT在线测试工具:https://mqttx.app/zh

MQTT(Eclipse Paho)库安装与实例

注意:需要std=c++14以上才能使用

  Eclipse Paho C++是一个跨平台的MQTT客户端实现,可以用于在C++应用程序中发送和接收MQTT消息。它支持许多不同的传输协议(如TCP、WebSocket、SSL等),并提供了多种QoS级别。开发中常使用这个。

安装步骤:

# 1、依赖
sudo apt-get install build-essential gcc make cmake libssl-dev doxygen graphviz

# 2、编译安装 c 库
# 进入 https://github.com/eclipse/paho.mqtt.c 下载 v1.3.8 版的源码
cd paho.mqtt.c-1.3.8
cmake -Bbuild -H. -DPAHO_ENABLE_TESTING=OFF -DPAHO_BUILD_STATIC=ON \
    -DPAHO_WITH_SSL=ON -DPAHO_HIGH_PERFORMANCE=ON
sudo cmake --build build/ --target install
sudo ldconfig

# 3、编译安装 c++ 库
# 进入 https://github.com/eclipse/paho.mqtt.cpp 下载 v1.2.0 版的源码
cd paho.mqtt.cpp-1.2.0
cmake -Bbuild -H. -DPAHO_BUILD_STATIC=ON \
    -DPAHO_BUILD_DOCUMENTATION=TRUE -DPAHO_BUILD_SAMPLES=TRUE
sudo cmake --build build/ --target install
sudo ldconfig

# ldconfig命令作用:https://linux265.com/course/linux-command-ldconfig.html

客户端代码示例:

【mqtt_client.hpp】

#ifndef __MQTT_CLIENT_TO_CLOUD_HPP__
#define __MQTT_CLIENT_TO_CLOUD_HPP__

#include <mqtt/async_client.h>   // mqtt库头文件
#include <mqtt/topic.h>

namespace cloud {
    // 消息处理器
    using message_handler = std::function<void(const std::string&)>;
    class mqtt_client {
    public:
        mqtt_client();
        ~mqtt_client();
        void send(const std::string& message);
        void set_message_handler(message_handler cb);
    private:
        //本地测试:mosquitto
        // static constexpr const char* BROKER_HOST = "localhost:1883";
        //公共mqtt broker:MQTTX
        static constexpr const char* BROKER_HOST = "broker.emqx.io:1883";
        //云端测试:mosquitto
        // static constexpr const char* BROKER_HOST = "124.XXX.XXX.XXX:1883";
    private:
        mqtt::async_client cli_;
        mqtt::topic        topic_;
    };
}  // namespace cloud
#endif

【mqtt_client.cpp】

#include <iostream>
#include <string>

#include "mqtt_client.hpp"

using namespace std;

namespace cloud {
    // 构造器
    mqtt_client::mqtt_client()
        // 1.mqtt服务器地址 2.mqtt客户端id 3.mqtt协议版本
        : cli_(BROKER_HOST, "client", mqtt::create_options(MQTTVERSION_5))
        // 1.该主题应用到哪个客户端 2.订阅/发布的主题 3.默认的mqtt消息质量
        , topic_(cli_,"haojuhu", 1) {
        // 断开连接回调函数
        cli_.set_connection_lost_handler([this](const string& info) {
            std::cout<<"mqtt connection lost <" << info << ">, reconnting"<<std::endl;
            cli_.reconnect(); // 重新连接
        });
        // 连接成功回调函数
        cli_.set_connected_handler([this](const string& info) {
            std::cout << "mqtt connected <" << info << ">"<<std::endl;
            topic_.subscribe(mqtt::subscribe_options(true));    // client订阅topic[haojuhu]
            topic_.publish("online");     // client发布消息"online"至topic[haojuhu]
        });
    }
    // 析构函数实现
    mqtt_client::~mqtt_client() {
        cli_.disconnect();
        cli_.disable_callbacks();
    }

    /**
     * @brief       Publish message to topic,发布消息给topic
     * @param[in]   message The message payload
     */
    void mqtt_client::send(const string& message) { 
        topic_.publish(message); 
    }

    /**
     * @brief       Set mqtt message handler,设置mqtt消息处理句柄(也就是函数对象cb)
     * @note        The mqtt connection will established here
     * @param[in]   cb  The message handler
     */
    void mqtt_client::set_message_handler(message_handler cb) {
        // 设置消息回调函数
        cli_.set_message_callback([cb](mqtt::const_message_ptr message) {
            cb(message->get_payload_str());   // 执行函数cb
        });
        // 设置链接选项
        auto opts = mqtt::connect_options_builder()
                        .mqtt_version(MQTTVERSION_5)
                        .clean_start(true)
            			.user_name("用户名")
                        .password("密码")
                        .finalize();
        cli_.connect(opts);
    }
}  // namespace cloud

【main.cpp】

#include <iostream>
#include <string>
#include <map>
#include "mqtt_client.hpp"

using namespace std;

/**
 * @brief               消息处理
 * @param[in]   data    The message payload from cloud
 */
void on_cloud_message(const string& data) {
    std::cout<<"received data is: "<<data<<std::endl;
}

int main(int argc,char **argv) {
    cloud::mqtt_client g_client;    // 定义一个mqtt客户端
    std::cout << "[CLOUD] listen starting"<<std::endl;
    g_client.set_message_handler(on_cloud_message);     // 开启mqtt clinet监听消息,消息处理函数为on_cloud_message
    while(true) {
        std::cout << "运行中..."<<std::endl;
        this_thread::sleep_for(10s);
        g_client.send("online...");     // 确保与mqtt broker server建立连接之后再publish!!!
    }
    return 0;
}

编译运行:g++ std=c++14 main.cpp mqtt_client.cpp -o main -lpaho-mqttpp3 -lpaho-mqtt3a ./main

报错 /lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by ...):https://blog.csdn.net/zhuiqiuzhuoyue583/article/details/80150207

原文地址:https://blog.csdn.net/qq_40344790/article/details/131015260

posted @ 2023-10-16 00:25  黄河大道东  阅读(805)  评论(0编辑  收藏  举报