Hi,大家好!今天我们来认识一下物联网通信中重要的通信协议MQTT。
unsetunset1、MQTT是什么unsetunset
MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息协议,设计用于在低带宽、不稳定或高延迟的网络环境中传输消息。MQTT最初由IBM开发,后来成为OASIS标准,广泛用于物联网(IoT)应用和其他需要高效消息传递的场景。
MQTT是轻量级基于代理的发布/订阅的消息传输协议,它可以通过很少的代码和带宽和远程设备连接。例如通过卫星和代理连接,通过拨号和医疗保健提供者连接,以及在一些自动化或小型设备上,而且由于小巧,省电,协议开销小和能高效的向一和多个接收者传递信息,故同样适用于移动应用设备上。
- 早在1999年,IBM的Andy Stanford-Clark博士以及Arcom公司ArlenNipper博士发明了MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)技术 。
- MQTT的话题是他们在谈论开源物联网平台Pachube时提到的。Stanford-Clark认为Pachube很酷,其不足之处是不具备真正的推送功能。你需要不断的进行轮询才能得到即时数据。这正是MQTT能够实现的,他提到了使用推送通信系统的石油管道检测系统。
unsetunset2、MQTT协议的关键概念和特性unsetunset
以下是MQTT协议的一些关键概念和特性:
1. 发布/订阅模型:
MQTT采用发布/订阅模型,消息的发送者称为发布者(Publisher),而消息的接收者称为订阅者(Subscriber)。发布者将消息发布到主题(Topic),而订阅者可以选择订阅特定主题以接收相关消息。
2. 主题(Topic):
主题是MQTT中消息的分类标识,用于将消息发送到特定的目标。订阅者可以通过订阅特定主题来接收与该主题相关的消息。主题可以是层次结构的,例如:home/living-room/temperature
,其中home
是根主题,living-room
是home
的子主题,temperature
是living-room
的子主题。
3. 消息质量等级(QoS):
MQTT支持不同的消息质量等级,用于确保消息传递的可靠性。共有三个等级:
- QoS 0: 最多一次传递,消息可能会丢失或重复。
- QoS 1: 至少一次传递,确保消息至少被接收一次。
- QoS 2: 刚好一次传递,确保消息仅被接收一次。
4. 保留消息:
发布者可以发送保留消息,这是一个持久的消息,当有新订阅者订阅与保留消息相匹配的主题时,将立即发送该消息。这对于传递重要信息或者初始化状态很有用。
5. 遗嘱消息(Will Message):
连接到MQTT代理的客户端可以指定一个遗嘱消息。如果客户端非正常断开连接,代理将自动发布遗嘱消息到预定的主题。这可用于通知其他客户端某个设备的状态变化。
6. 保持活动性(Keep Alive):
MQTT使用保持活动性机制来确保客户端与代理之间的连接保持活动。客户端会定期向代理发送保持活动性的消息,如果代理在指定的时间内未收到客户端的消息,将关闭连接。
7. 连接过程:
MQTT的连接过程包括客户端向代理发送连接请求、代理响应并确认连接、客户端发送连接信息、代理确认连接信息。在这个过程中,客户端和代理之间会协商使用的MQTT版本、连接的用户名和密码、保持活动性时间等。
8. 安全性:
MQTT本身并没有内建的安全性机制,但可以通过TLS/SSL进行加密传输。此外,可以通过用户名和密码进行身份验证,以及通过访问控制列表(ACL)限制客户端的访问权限。
unsetunset3、MQTT客户端代码示例unsetunset
实现一个完整的MQTT协议是一个庞大而复杂的任务,因为MQTT涉及到多个方面,包括连接、发布/订阅、消息质量等级等。下面是一个简化的C 实现的示例,用于建立一个基本的MQTT客户端,演示连接到MQTT代理服务去发布/订阅消息。
该示例使用了 Eclipse Paho MQTT C 客户端库,该库提供了MQTT协议的C 实现。有兴趣的小获取可以去官网了解一下。
首先,确保你已经安装了 Paho MQTT C 客户端库。可以从Paho官网获取该库。
接下来,以下是一个简单的C 示例:
代码语言:javascript复制#include <iostream>
#include <mqtt/async_client.h>
class MQTTCallbacks : public virtual mqtt::callback, public virtual mqtt::iaction_listener {
void connectionLost(const std::string& cause) override {
std::cout << "Connection lost: " << cause << std::endl;
}
void deliveryComplete(mqtt::delivery_token_ptr tok) override {
std::cout << "Message delivered" << std::endl;
}
void onSuccess(const mqtt::token& tok) override {
std::cout << "Action successful" << std::endl;
}
void onFailure(const mqtt::token& tok) override {
std::cout << "Action failed" << std::endl;
}
};
int main() {
const std::string brokerAddress = "tcp://localhost:1883";
const std::string clientId = "cpp_mqtt_client";
const std::string topic = "test/topic";
mqtt::async_client client(brokerAddress, clientId);
MQTTCallbacks callbacks;
client.set_callback(callbacks);
mqtt::connect_options connOpts;
connOpts.set_keep_alive_interval(20);
connOpts.set_clean_session(true);
try {
std::cout << "Connecting to the broker..." << std::endl;
client.connect(connOpts)->wait();
std::cout << "Connected!" << std::endl;
std::string payload = "Hello, MQTT!";
mqtt::message_ptr pubmsg = mqtt::make_message(topic, payload);
pubmsg->set_qos(1);
client.publish(pubmsg)->wait();
std::cout << "Message published" << std::endl;
client.subscribe(topic, 1)->wait();
while (true) {
// Continue to keep the program running
std::this_thread::sleep_for(std::chrono::seconds(1));
}
client.unsubscribe(topic)->wait();
client.disconnect()->wait();
} catch (const mqtt::exception& exc) {
std::cerr << "Error: " << exc.what() << std::endl;
return 1;
}
return 0;
}
该示例假定了本地运行的MQTT代理地址为 tcp://localhost:1883
,客户端连接后发布了一条消息到主题 test/topic
,并订阅了该主题。实际开发中我们需要修改 brokerAddress
和其他参数。
需要说明的是这只是一个简单的示例,实际上MQTT的实现要更加复杂,需要处理连接丢失、重连、消息质量等级等情况。在实际应用中,建议使用现成的MQTT客户端库,以确保正确性和稳定性。
unsetunset小结unsetunset
MQTT在实际开发中需要学习的内容有很多,而且很多细节需要注意。希望正在学习MQTT协议的小伙伴通过本节内容对MQTT协议有个初步的认识。
题外话:学习技术是一个慢慢沉淀的过程。不积跬步无以至千里,技术同样如此。希望小伙伴们在以后的技术路上坚持下去,并到达一片开阔的境地。