C语言实现mosquitto发布、订阅消息
1、安装mosquitto
1.1、编译安装
- 安装依赖
sudo apt-get install libssl-dev
sudo apt-get install uuid-dev
sudo apt-get install cmake
- 下载资源包
下载地址:https://mosquitto.org/download/
wget https://mosquitto.org/files/source/mosquitto-1.6.12.tar.gz
- 解压
tar -zxvf mosquitto-1.6.12.tar.gz
- 进入源码目录
cd mosquitto-1.6.12/
- 编译、安装
make
sudo make install
- 链接
当我们在使用mosquitto的时侯库要我们自己链接。
$(CC) mqtt_sub.c -I ./mosq/mosquitto-1.6.12/lib -L ./mosq/mosquitto-1.6.12/lib -lmosquitto
1.2、直接安装
- 安装服务器端
sudo apt-get install mosquitto
- 安装客户端
sudo apt install mosquitto-clients
2、发布
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "mosquitto.h"
#define HOST "xxxxxx"
#define PORT 1883
#define KEEP_ALIVE 60
#define MSG_MAX_SIZE 512
static int running = 1;
void my_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
printf("Call the function: my_connect_callback\n");
}
void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
{
printf("Call the function: my_disconnect_callback\n");
running = 0;
}
void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{
printf("Call the function: my_publish_callback\n");
}
int main()
{
int ret;
struct mosquitto *mosq;
char buff[MSG_MAX_SIZE];
//初始化libmosquitto库
ret = mosquitto_lib_init();
if(ret){
printf("Init lib error!\n");
return -1;
}
//创建一个发布端实例
mosq = mosquitto_new("pub_test", true, NULL);
if(mosq == NULL){
printf("New pub_test error!\n");
mosquitto_lib_cleanup();
return -1;
}
//设置回调函数
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
mosquitto_publish_callback_set(mosq, my_publish_callback);
// 连接至服务器
// 参数:句柄、ip(host)、端口、心跳
ret = mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE);
if(ret){
printf("Connect server error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
printf("Start!\n");
//mosquitto_loop_start作用是开启一个线程,在线程里不停的调用 mosquitto_loop() 来处理网络信息
int loop = mosquitto_loop_start(mosq);
if(loop != MOSQ_ERR_SUCCESS)
{
printf("mosquitto loop error\n");
return 1;
}
while(fgets(buff, MSG_MAX_SIZE, stdin) != NULL)
{
/*发布消息*/
mosquitto_publish(mosq,NULL,"test",strlen(buff)+1,buff,0,0);
memset(buff,0,sizeof(buff));
}
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
printf("End!\n");
return 0;
}
3、订阅
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mosquitto.h"
#define HOST "xxxxxxx"
#define PORT 1883
#define KEEP_ALIVE 60
#define MSG_MAX_SIZE 512
// 定义运行标志决定是否需要结束
static int running = 1;
void my_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
printf("Call the function: on_connect\n");
if(rc){
// 连接错误,退出程序
printf("on_connect error!\n");
exit(1);
}else{
// 订阅主题
// 参数:句柄、id、订阅的主题、qos
if(mosquitto_subscribe(mosq, NULL, "test", 2)){
printf("Set the topic error!\n");
exit(1);
}
}
}
void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc)
{
printf("Call the function: my_disconnect_callback\n");
running = 0;
}
void my_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
printf("Call the function: on_subscribe\n");
}
void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
printf("Call the function: on_message\n");
printf("Recieve a message of %s : %s\n", (char *)msg->topic, (char *)msg->payload);
if(0 == strcmp(msg->payload, "quit")){
mosquitto_disconnect(mosq);
}
}
int main()
{
int ret;
struct mosquitto *mosq;
// 初始化mosquitto库
ret = mosquitto_lib_init();
if(ret){
printf("Init lib error!\n");
return -1;
}
// 创建一个订阅端实例
// 参数:id(不需要则为NULL)、clean_start、用户数据
mosq = mosquitto_new("sub_test", true, NULL);
if(mosq == NULL){
printf("New sub_test error!\n");
mosquitto_lib_cleanup();
return -1;
}
// 设置回调函数
// 参数:句柄、回调函数
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
mosquitto_message_callback_set(mosq, my_message_callback);
// 连接至服务器
// 参数:句柄、ip(host)、端口、心跳
ret = mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE);
if(ret){
printf("Connect server error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
// 开始通信:循环执行、直到运行标志running被改变
printf("Start!\n");
while(running)
{
mosquitto_loop(mosq, -1, 1);
}
// 结束后的清理工作
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
printf("End!\n");
return 0;
}
这里我单独说一下回调函数,这里有几个回调函数,如下
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_disconnect_callback_set(mosq, my_disconnect_callback);
mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
mosquitto_message_callback_set(mosq, my_message_callback);
- mosquitto_subscribe_callback_set()
这个函数叫做【中间函数】或者【登记回调函数】,他的职能是监控事件的发生。
- my_subscribe_callback
相应的这个函数就是回调函数,他是事件发生后实现的方法。
- 回调函数的执行主要分为一下几个步骤:
1、主函数需要调用回调函数
2、中间函数登记回调函数
3、触发回调函数事件
4、调用回调函数
5、响应回调事件
举一个例子,某天你去超市买东西,你要买的东西没有了,然后你给超市店员说你买的东西到了给你打电话,过了几天东西到了,店员给你打电话,然后你去超市买了东西。
这个例子里面,店员是登记回调函数
,电话号码是回调函数
,东西到了是触发回调事件
,店员给你打电话是调用回调函数
,你去取东西是相应回调事件