以前一直在用paho.mqtt.c,近期C++项目中,使用C++版本,例子记录如下:
#include <iostream> // 引入输入输出流库
#include <cstdlib> // 引入C标准库
#include <string> // 引入字符串库
#include <thread> // 引入线程库
#include <atomic> // 引入原子操作库
#include <chrono> // 引入时间库
#include <cstring> // 引入字符串操作库
#include "mqtt/async_client.h" // 引入MQTT异步客户端库
using namespace std; // 使用标准命名空间
const string DFLT_SERVER_ADDRESS { "mqtt://localhost:1883" }; // 默认服务器地址
const string CLIENT_ID { "paho_cpp_async_publish" }; // 客户端ID
const string PERSIST_DIR { "./persist" }; // 持久化目录
const string TOPIC { "hello" }; // MQTT主题
const char* PAYLOAD1 = "Hello World!"; // 消息负载1
const char* PAYLOAD2 = "Hi there!"; // 消息负载2
const char* PAYLOAD3 = "Is anyone listening?"; // 消息负载3
const char* PAYLOAD4 = "Someone is always listening."; // 消息负载4
const char* LWT_PAYLOAD = "Last will and testament."; // 遗嘱消息负载
const int QOS = 1; // 服务质量等级
const auto TIMEOUT = std::chrono::seconds(10); // 超时时间
/////////////////////////////////////////////////////////////////////////////
// 回调类,用于处理MQTT客户端事件
class callback : public virtual mqtt::callback
{
public:
void connection_lost(const string& cause) override { // 连接丢失事件
cout << "
Connection lost" << endl;
if (!cause.empty())
cout << "\tcause: " << cause << endl;
}
void delivery_complete(mqtt::delivery_token_ptr tok) override { // 消息发送完成事件
cout << "\tDelivery complete for token: "
<< (tok ? tok->get_message_id() : -1) << endl;
}
};
/////////////////////////////////////////////////////////////////////////////
// 动作监听器类
class action_listener : public virtual mqtt::iaction_listener
{
protected:
void on_failure(const mqtt::token& tok) override { // 失败事件
cout << "\tListener failure for token: "
<< tok.get_message_id() << endl;
}
void on_success(const mqtt::token& tok) override { // 成功事件
cout << "\tListener success for token: "
<< tok.get_message_id() << endl;
}
};
/////////////////////////////////////////////////////////////////////////////
// 派生的动作监听器,用于发布事件
class delivery_action_listener : public action_listener
{
atomic<bool> done_; // 完成标志
void on_failure(const mqtt::token& tok) override { // 失败事件
action_listener::on_failure(tok);
done_ = true;
}
void on_success(const mqtt::token& tok) override { // 成功事件
action_listener::on_success(tok);
done_ = true;
}
public:
delivery_action_listener() : done_(false) {} // 构造函数
bool is_done() const { return done_; } // 获取完成标志
};
/////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// 创建一个普通的MQTT客户端,不需要持久化会话或客户端ID,除非使用持久化,否则本地库需要ID来识别持久化文件。
string address = (argc > 1) ? string(argv[1]) : DFLT_SERVER_ADDRESS,
clientID = (argc > 2) ? string(argv[2]) : CLIENT_ID;
cout << "Initializing for server '" << address << "'..." << endl;
mqtt::async_client client(address, clientID, PERSIST_DIR); // 创建异步客户端
callback cb; // 创建回调对象
client.set_callback(cb); // 设置回调
auto connOpts = mqtt::connect_options_builder() // 创建连接选项
.clean_session() // 清除会话
.will(mqtt::message(TOPIC, LWT_PAYLOAD, strlen(LWT_PAYLOAD), QOS, false)) // 设置遗嘱消息
.finalize(); // 完成构建
cout << " ...OK" << endl;
try {
cout << "\nConnecting..." << endl;
mqtt::token_ptr conntok = client.connect(connOpts); // 连接服务器
cout << "Waiting for the connection..." << endl;
conntok->wait(); // 等待连接完成
cout << " ...OK" << endl;
// 使用消息指针发送消息。
cout << "\nSending message..." << endl;
mqtt::message_ptr pubmsg = mqtt::make_message(TOPIC, PAYLOAD1); // 创建消息
pubmsg->set_qos(QOS); // 设置服务质量等级
client.publish(pubmsg)->wait_for(TIMEOUT); // 发送消息并等待超时
cout << " ...OK" << endl;
// 现在尝试使用项目化的发布。
cout << "\nSending next message..." << endl;
mqtt::delivery_token_ptr pubtok; // 创建发布令牌指针
pubtok = client.publish(TOPIC, PAYLOAD2, strlen(PAYLOAD2), QOS, false); // 发送消息
cout << " ...with token: " << pubtok->get_message_id() << endl; // 输出消息ID
cout << " ...for message with " << pubtok->get_message()->get_payload().size()
<< " bytes" << endl; // 输出消息大小
pubtok->wait_for(TIMEOUT); // 等待超时
cout << " ...OK" << endl;
// 现在尝试使用一个监听器发送消息
cout << "\nSending next message..." << endl;
action_listener listener; // 创建动作监听器
pubmsg = mqtt::make_message(TOPIC, PAYLOAD3); // 创建消息
pubtok = client.publish(pubmsg, nullptr, listener); // 发送消息并设置监听器
pubtok->wait(); // 等待发送完成
cout << " ...OK" << endl;
// 最后尝试使用一个监听器,但没有令牌
cout << "\nSending final message..." << endl;
delivery_action_listener deliveryListener; // 创建派生的动作监听器
pubmsg = mqtt::make_message(TOPIC, PAYLOAD4); // 创建消息
client.publish(pubmsg, nullptr, deliveryListener); // 发送消息并设置监听器
while (!deliveryListener.is_done()) { // 等待监听器完成
this_thread::sleep_for(std::chrono::milliseconds(100));
}
cout << "OK" << endl;
// Double check that there are no pending tokens
auto toks = client.get_pending_delivery_tokens(); // 获取未完成的发布令牌
if (!toks.empty())
cout << "Error: There are pending delivery tokens!" << endl; // 如果存在未完成的发布令牌,输出错误信息
// Disconnect
cout << "\nDisconnecting..." << endl;
client.disconnect()->wait(); // 断开连接并等待完成
cout << " ...OK" << endl;
}
catch (const mqtt::exception& exc) { // 捕获异常
cerr << exc.what() << endl; // 输出异常信息
return 1; // 返回错误码1
}
return 0; // 正常退出,返回0
}