目录
一、简介
在学习mosquitto库之前,我们需要掌握MQTT协议的相关知识。MQTT简单说就是一个轻量级的消息传输协议,基于发布/订阅模型,适用于物联网(IoT)等需要低带宽、高延迟和不可靠网络的场景。通过MQTT的学习,我们可以通过使用mosquitto库进行连接阿里云服务器进行实践。
二、MQTT协议
1、概念
MQTT(Message Queuing Telemetry Transport)是一种轻量级的开放式消息协议,设计用于物联网(IoT)和移动设备之间的通信。
实现MQTT协议需要客户端和服务器端通讯完成,在通讯过程中,MQTT协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。
MQTT传输的消息分为:主题(Topic)和负载(payload)两部分。Topic可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容(payload)。payload,可以理解为消息的内容,是指订阅者具体要使用的内容。
MQTT会构建底层网络传输:它将建立客户端到服务器的连接,提供两者之间的一个有序的、无损的、基于字节流的双向传输。当应用数据通过MQTT网络发送时,MQTT会把与之相关的服务质量(QoS)和主题名(Topic)相关连。
2、发布/订阅模型
发布者和订阅者可以部署在不同的物理位置或网络环境中,它们通过连接到同一个 MQTT 代理来进行通信。发布者只需要将消息发布到一个特定的主题(Topic),而不需要关心有哪些订阅者会接收这些消息。类似地,订阅者只需要订阅感兴趣的主题,而不需要关心消息是由哪些发布者发送的。这种解耦合设计,提供了高度灵活性、可扩展性和适应性,使得它成为物联网和其他分布式系统中广泛应用的消息传递协议。
3、服务质量
MQTT 提供了三种服务质量(QoS)级别,以满足不同的可靠性需求。
QoS 0 - 最多一次
消息发布者发送消息后,不会收到任何确认或者保证消息是否被成功接收。消息会被发送一次,如果因为某些原因消息未能成功传递到接收者,发布者也不会重传消息。这是最低开销和最低保证的级别,适用于不需要严格可靠性的场景。
QoS 1 - 至少一次
消息发布者会收到确认(PUBACK)以确保消息至少被成功传递一次到接收者。如果发布者没有在规定时间内收到确认,会尝试重新发送消息,直到收到确认。这种级别保证了消息不会丢失,但可能会导致消息重复。
QoS 2 - 只有一次
这是最高级别的 QoS,确保每条消息只被传递一次到接收者,不会重复传递。发布者会收到两个确认(PUBREC 和 PUBCOMP),确保消息已经精确地传递到接收者。这种级别提供了最高的消息传输可靠性,但会增加一些开销和延迟。
4、名词解释
(1)订阅(Subscription):订阅包含主题筛选器(Topic Filter)和最大服务质量(QoS)。订阅会与一个会话(Session)关联。一个会话可以包含多个订阅。每一个会话中的每个订阅都有一个不同的主题筛选器。
(2)会话(Session):每个客户端与服务器建立连接后就是一个会话,客户端和服务器之间有状态交互。会话存在于一个网络之间,也可能在客户端和服务器之间跨越多个连续的网络连接。
(3) 主题名(Topic Name):连接到一个应用程序消息的标签,该标签与服务器的订阅相匹配。服务器会将消息发送给订阅所匹配标签的每个客户端。
(4)主题筛选器(Topic Filter):一个对主题名通配符筛选器,在订阅表达式中使用,表示订阅所匹配到的多个主题。
(5)负载(Payload):消息订阅者所具体接收的内容。
三、mosquitto库
mosquitto库提供了一组用于实现 MQTT 客户端功能的 API。通过使用这个库,开发者可以在自己的应用程序中集成 MQTT 功能,实现消息的发布、订阅、连接管理等操作。
1、初始化库
int mosquitto_lib_init(void);
该函数用于初始化库。在使用其他 Mosquitto API 函数之前,必须首先调用这个函数。它负责设置一些全局状态和数据结构,使库处于可用状态。
2、清理库
void mosquitto_lib_cleanup(void);
该函数用于清理库。在程序结束时,调用这个函数来释放由库分配的资源和进行必要的清理操作。确保在调用 mosquitto_lib_cleanup()
之前已经停止了所有与 Mosquitto 客户端相关的活动,并销毁了所有 Mosquitto 客户端实例。
3、创建实例
struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *obj);
该函数用于创建一个新的 MQTT 客户端实例。在使用 Mosquitto 库与 MQTT 代理进行通信时,首先需要创建一个 MQTT 客户端实例。
参数说明:
id
:客户端的唯一标识符。如果传入NULL
,则库将自动生成一个随机的客户端 ID。对于持久会话(clean_session
为false
),必须提供一个唯一的 ID。clean_session
:布尔值,指定会话类型。true
表示创建一个新的干净会话,false
表示持久会话。obj
:用户定义的数据指针,可在回调函数中使用。
4、销毁实例
void mosquitto_destroy(struct mosquitto *mosq);
该函数用于销毁一个 MQTT 客户端实例并释放与其相关的所有资源。当一个 MQTT 客户端实例不再需要时,应该调用这个函数进行清理,以避免内存泄漏。
5、设置信息
int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password);
用于设置 MQTT 客户端的用户名和密码,以便进行身份验证。当连接到需要身份验证的 MQTT 代理时,可以使用这个函数来提供必要的凭据。
6、连接回调
/* 回调函数原型 */
void on_connect(struct mosquitto *mosq, void *obj, int rc);
/* 设置连接回调函数 */
int mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));
该函数主要作用是设置一个回调函数,当 MQTT 客户端接收到来自代理的连接确认(也即连接成功或失败的响应)时,会调用这个回调函数。通过这种方式,程序可以在连接成功或失败时执行特定的操作。
参数说明:
mosq
: 指向 Mosquitto 实例的指针。on_connect
: 当客户端连接到代理时被调用的回调函数。struct mosquitto *mosq
: 指向 Mosquitto 实例的指针。void *obj
: 指向用户自定义对象的指针。int rc
: 连接请求的返回代码。
7、网络连接
int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive);
该函数用于连接到 MQTT 代理。它尝试建立客户端与代理之间的网络连接。
参数说明:
mosq
: 指向一个 Mosquitto 实例的指针。host
: 代理的主机名或 IP 地址。port
: 代理的端口号。keepalive
: 以秒为单位的 keepalive 时间间隔。客户端在该间隔内如果没有发送任何消息,就会发送一个 ping 消息来保持连接。
8、进行处理
int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets);
用于处理网络通信和回调调用。它将进入一个无限循环,处理传入和传出的消息,直到客户端断开连接或遇到不可恢复的错误。
参数说明:
mosq
: 指向一个 Mosquitto 实例的指针。timeout
: 在调用mosquitto_loop
之前等待的最大毫秒数。设置为 -1 表示使用默认的超时时间。max_packets
: 在每次循环中处理的最大消息数。设置为 1 表示每次循环只处理一个消息。
四、连接阿里云并实时上报温度
相关代码我都放在github中了,大家可以自行查看:hongboxin/MQTT (github.com)
运行后(我这里使用的sht20温湿度传感器)
可以在阿里云的物模型看到刚刚上传的数据