前言
Mosquitto库是一个开源的消息代理项目,用于实现MQTT(Message Queuing Telemetry Transport)协议。MQTT是一种轻量级的通信协议,适用于低带宽、高延迟或不稳定网络环境下的物联网设备通信。Mosquitto库提供了MQTT协议的服务器和客户端实现,可以用于构建物联网应用和设备之间的通信。Mosquitto库支持多种平台和编程语言,并提供了丰富的功能和灵活的配置选项。
一、MQTT简介
MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议;Mosquitto是一个实现了MQTT3.1协议的代理服务器,由MQTT协议创始人之一的Andy Stanford-Clark开发,应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备
二、Mosquitto安装
1.Ubuntu下安装mosquitto
-
wget下载源码包
wget http://mosquitto.org/files/source/mosquitto-1.5.5.tar.gz
2.解压
tar -xzvf mosquitto-1.5.5.tar.gz
3.进入目录,编译下载安装
cd mosquitto-1.5.5/
make
sudo make install
make出现 fatal error: openssl/opensslconf.h: No such file or directory
输入以下命令安装
重新make
若出现错误,看第四点
4.注意事项:
可能出现问题及解决方法
【1】编译找不到openssl/ssl.hsudo apt-get install libssl-dev
【2】编译过程g++命令未找到:sudo apt-get install g++
【3】编译过程找不到ares.hsudo apt-get install libc-ares-dev
【4】编译过程找不到uuid/uuid.hsudo apt-get install uuid-dev
【5】使用过程中找不到libmosquitto.so.1 error while loading shared libraries: libmosquitto.so.1: cannot open shared object file:No such file or directory
【解决方法】——修改libmosquitto.so位置
创建链接sudo ln -s /usr/local/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1
更新动态链接库sudo ldconfig
2.测试mosquitto订阅与发布
1.mosquitto broker配置
查看mosquitto配置文件在mosquitto文件夹下vim mosquitto.conf
mosquitto配置文件默认即可。如有需求可按需修改。
2.启动
mosquitto [-c config file] [ -d | --daemon ] [-p port number] [-v]
参数说明:
-c 后面跟的是启动mosquitto可以调整的参数,比如是否开启基本认证,端口是什么,SSL单向和双向的认证配置等等。
-d 表示MQTT mosquitto将在后台运行。
-p 代表当前的mosquitto服务实例启动以后,其监听端口号,这个配置覆盖[-c config file] 指定的配置文件中的端口。
-v 代码调试模式(verbose)在终端输出更多的信息 。
3.订阅——mosquitto_sub
mosquitto_sub 命令参数说明
1. -c 设定‘clean session’为无效状态,这样一直保持订阅状态,即便是已经失去连接,如果再次连接仍旧能够接收的断开期间发送的消息。
2. -d 打印debug信息
3. -h 指定要连接的域名 默认为localhost
4. -i 指定clientId
5. -I 指定clientId前缀
6. -k keepalive 每隔一段时间,发PING消息通知broker,仍处于连接状态。 默认为60秒。
7. -q 指定希望接收到QoS为什么的消息 默认QoS为0
8. -R 不显示陈旧的消息
9. -t 订阅topic
10. -v 打印消息
11. --will-payload 指定一个消息,该消息当客户端与broker意外断开连接时发出。该参数需要与--will-topic一起使用
12. --will-qos Will的QoS值。该参数需要与--will-topic一起使用
13. --will-retain 指定Will消息被当做一个retain消息(即消息被广播后,该消息被保留起来)。该参数需要与--will-topic一起使用
14. --will-topic 用户发送Will消息的topic
4.发布——mosquitto_pub
mosquitto_pub 命令参数说明
1. -d 打印debug信息
2. -f 将指定文件的内容作为发送消息的内容
3. -h 指定要连接的域名 默认为localhost
4. -i 指定要给哪个clientId的用户发送消息
5. -I 指定给哪个clientId前缀的用户发送消息
6. -m 消息内容
7. -n 发送一个空(null)消息
8. -p 连接端口号
9. -q 指定QoS的值(0,1,2)
10. -t 指定topic
11. -u 指定broker访问用户
12. -P 指定broker访问密码
13. -V 指定MQTT协议版本
14. --will-payload 指定一个消息,该消息当客户端与broker意外断开连接时发出。该参数需要与--will-topic一起使用
15. --will-qos Will的QoS值。该参数需要与--will-topic一起使用
16. --will-retain 指定Will消息被当做一个retain消息(即消息被广播后,该消息被保留起来)。该参数需要与--will-topic一起使用
17. --will-topic 用户发送Will消息的topic
5.关闭
# 查看mosquitto服务进程ID
ps -aux | grep mosquitto
# 杀掉服务进程
# PID 为上一步查找的ID
kill -9 PID
6.测试
第一个终端(订阅)
mosquitto_sub -h localhost -p 1883 -t "test" -v
在打开第二个终端(发布)
mosquitto_pub -h localhost -p 1883 -t "test" -m "hello world"
第一个终端(订阅)
第二个终端(发布)
出现下面错误看注意事项第5点解决
三.mosquitto库函数实现上述订阅与发布
常见API:
1.MQTT初始化
int mosquitto_lib_init(void)
功能:
使用mosquitto库函数前,要先初始化,使用之后就要清除。清除函数;int mosquitto_lib_cleanup()
返回值:MOSQ_ERR_SUCCESS
2.MQTT清除
int mosquitto_lib_cleanup(void)
功能:
使用MQTT之后,清除工作
返回值MOSQ_ERR_SUCCESS
3.新建客户端
struct mosquitto *mosquitto_new(const char * id, bool clean_session, void * obj)
参数
id:如果为NULL,将生成一个随机客户端ID。如果id为NULL,clean_session必须为true。
clean_session:设置为true以指示代理在断开连接时清除所有消息和订阅,设置为false以指示其保留它们,客户端将永远不会在断开连接时丢弃自己的传出消息就是断开后是否保留订阅信息true/false
obj:用户指针,将作为参数传递给指定的任何回调
返回
成功时返回结构mosquitto的指针,失败时返回NULL,询问errno以确定失败的原因:ENOMEM内存不足。EINVAL输入参数无效。
4.释放客户端
void mosquitto_destroy(struct mosquitto * mosq)
功能
释放客户端
参数:mosq: struct mosquitto指针
5.设置账号密码
int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *passworp)
参数
struct mosquitto *mosq :客户端
const char *username : 以字符串形式发送的用户名,或以NULL形式关闭认证。
const char *passworp:以字符串形式发送的密码。 当用户名有效时,设置为NULL,以便只发送一个用户名。
返回值
成功时返回MOSQ_ERR_SUCCESS。
如果输入参数无效,返回MOSQ_ERR_INVAL。
如果发生内存不足的情况,返回MOSQ_ERR_NOMEM。
6.确认连接回调函数
void mosquitto_connect_callback_set(struct mosquitto * mosq, void (*on_connect)(struct mosquitto *mosq, void *obj, int rc) )
功能:连接确认回调函数,当代理发送CONNACK消息以响应连接时,将调用此方法。
参数:
struct mosquitto * mosq:客户端通配符
void (*on_connect):回调函数
struct mosquitto *mosq:客户端数据
void *obj:创建客户端的回调参数(mosquitto_new中提供的用户数据)
int rc:
0-成功
1-连接被拒绝(协议版本不可接受)
2-连接被拒绝(标识符被拒绝)
3-连接被拒绝(经纪人不可用)
4-255-保留供将来使用
7.断开连接回调函数
void mosquitto_disconnect_callback_set( struct mosquitto *mosq,void (*on_disconnect)( struct mosquitto *mosq,void *obj, int rc) );
/*功能:设置断开连接回调函数,当代理收到DISCONNECT命令并断开与客户端的连接,将调用on_disconnect。
参数:mosq: struct mosquitto指针
void (*on_connect)(struct mosquitto *mosq , void *obj, int rc) 回调函数 (参数:
mosq: struct mosquitto指针
obj:mosquitto_new中提供的用户数据
rc:0表示客户端已经调用mosquitto_disconnect,任何其他值,表示断开连接时意外的。)
8.连接MQTT代理/服务器
int mosquitto_connect(struct mosquitto * mosq, const char * host, int port, int keepalive)
功能: 连接到MQTT代理/服务器(主题订阅要在连接服务器之后进行)
参数:
struct mosquitto * mosq:客户端
const char * host:服务器ip
int port:服务器端口号
int keepalive:保持连接的时间间隔, 单位秒
返回:
MOSQ_ERR_SUCCESS 成功。
MOSQ_ERR_INVAL 如果输入参数无效。
MOSQ_ERR_ERRNO 如果系统调用返回错误。变量errno包含错误代码
9.断开MQTT代理/服务器
int mosquitto_disconnect( struct mosquitto * mosq )
功能:断开与代理/服务器的连接。
返回:
MOSQ_ERR_SUCCESS 成功。
MOSQ_ERR_INVAL 如果输入参数无效。
MOSQ_ERR_NO_CONN 如果客户端未连接到代理。
10.网络事件循环处理
int mosquitto_loop_start(struct mosquitto * mosq)
功能:网络事件循环处理函数,通过创建新的线程不断调用mosquitto_loop() 函数处理网络事件,不阻塞
参数:
struct mosquitto * mosq:客户端
返回:
MOSQ_ERR_SUCCESS 成功。
MOSQ_ERR_INVAL 如果输入参数无效。
MOSQ_ERR_NOT_SUPPORTED 如果没有线程支持。
11.发布主题
int mosquitto_publish(struct mosquitto * mosq, int * mid, const char * topic, int payloadlen, const void * payload, int qos, bool retain)
功能:主题发布的函数
参数:
struct mosquitto * mosq:客户端
int * mid:指向int的指针。如果不为NULL,则函数会将其设置为该特定消息的消息ID
const char * topic:要发布的主题,以'\0'结尾的字符串
int payloadlen:主题消息的内容长度
const void * payload:主题消息的内容,指向要发送的数据的指针,如果payloadlen >0,则它必须时有效的存储位置
int qos:整数值0、1、2指示要用于消息的服务质量
bool retain:设置为true以保留消息
返回:
MOSQ_ERR_SUCCESS 成功。
MOSQ_ERR_INVAL 如果输入参数无效。
MOSQ_ERR_NOMEM 如果发生内存不足的情况。
MOSQ_ERR_NO_CONN 如果客户端未连接到代理。
MOSQ_ERR_PROTOCOL 与代理进行通信时是否存在协议错误。
MOSQ_ERR_PAYLOAD_SIZE 如果payloadlen太大。
MOSQ_ERR_MALFORMED_UTF8 如果主题无效,则为UTF-8
MOSQ_ERR_QOS_NOT_SUPPORTED 如果QoS大于代理支持的QoS。
MOSQ_ERR_OVERSIZE_PACKET 如果结果包大于代理支持的包。
12.订阅主题
int mosquitto_subscribe( struct mosquitto * mosq, int * mid, const char * sub, i