mosquitto-2.0.9安装:https://blog.csdn.net/qq_36413982/article/details/115184473
mosquitto的API文档:/home/roger/src/mqtt/mosquitto/lib/mosquitto.h
https://mosquitto.org/api/files/mosquitto-h.html#mosquitto_loop_forever
mosquitto的API简单易用,基于回调函数编程。
订阅者mosquitto_sub.c:
#include "mosquitto.h"
#include "stdio.h"
#include "string.h"
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define MQTT_PORT 1883
struct mosquitto *mosq = NULL;
static const char *topic[] = {
"led",
"fan",
"curtain",
};
static int mosquitoto_subscribe_topic(const char *topic, int mid, int qos)
{
return mosquitto_subscribe(mosq, &mid, topic, qos);
}
static void mosq_on_connect_callback(struct mosquitto *mosq, void *obj, int mid)
{
int ret = 0;
for (int i = 0; i < ARR_SIZE(topic); i++)
{
if ((ret = mosquitoto_subscribe_topic(topic[i], i, 2)) == MOSQ_ERR_SUCCESS) //订阅主题
{
printf("subscribe success\n");
}
else
{
fprintf(stderr, "subscribe failed %d\n", ret);
}
}
if ((ret = mosquitoto_subscribe_topic("aaa", 0, 2)) == MOSQ_ERR_SUCCESS) //订阅主题
{
printf("subscribe success\n");
}
else
{
fprintf(stderr, "subscribe failed %d\n", ret);
}
}
static void mosq_on_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{
}
static void mosq_on_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
}
void mosq_on_message_get_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
{
if (message->payloadlen > 0)
{
printf("topic : %s, message : %s\r\n", message->topic, (char *)message->payload);
}
}
static void mosquitto_mqtt_init(char *host, int port, int keepalive)
{
mosquitto_lib_init(); //初始化mosquitto库
mosq = mosquitto_new(NULL, true, NULL); //创建一个mosquitto实例
if (mosq == NULL)
{
mosquitto_lib_cleanup();
printf("create mosquitto obj failed\r\n");
exit(1);
}
mosquitto_connect_callback_set(mosq, mosq_on_connect_callback); //设置连接成功回到函数
mosquitto_publish_callback_set(mosq, mosq_on_publish_callback); //设置发布成功回调函数
mosquitto_subscribe_callback_set(mosq, mosq_on_subscribe_callback); //设置订阅请求成功回调函数
mosquitto_message_callback_set(mosq, mosq_on_message_get_callback); //设置消息接收成功回调
int retries = 0;
//return val MOSQ_ERR_SUCCESS
while (mosquitto_connect(mosq, host, port, keepalive) != MOSQ_ERR_SUCCESS && retries < 5) //如果连接失败,尝试重复连接5次
{
retries++;
}
if (retries >= 5)
{
printf("connect mqtt broker failed\n");
mosquitto_destroy(mosq); //连接失败销毁
mosquitto_lib_cleanup();
exit(1);
}
printf("connect mqtt broker\r\n");
}
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: %s <host_ip>\r\n", argv[0]);
exit(1);
}
char *host = argv[1];
int port = MQTT_PORT;
int keepalive = 30;
mosquitto_mqtt_init(host, port, keepalive);
if (mosquitto_loop_start(mosq) != MOSQ_ERR_SUCCESS)
{
printf("failed to Call this once to start a new thread to process network traffic\n");
mosquitto_destroy(mosq); //连接失败销毁
mosquitto_lib_cleanup();
exit(1);
}
while (1)
{
// mosquitto_loop(mosq, -1, 1);
// printf("subscribe client running\n");
sleep(2);
}
mosquitto_destroy(mosq); //连接失败销毁
mosquitto_lib_cleanup();
return 0;
}
发布者mosquitto_pub.c:
#include <mosquitto.h>
#include "stdio.h"
#include "string.h"
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define MQTT_PORT 1883
enum topic_select {
TOPIC_LED = 0,
TOPIC_FAN,
TOPIC_CURTAIN,
};
typedef enum topic_select top_sel_t;
struct mosquitto *mosq = NULL;
static const char *topic[] = {
"led",
"fan",
"curtain",
};
static int mosquitoto_subscribe_topic(const char *topic, int mid, int qos)
{
return mosquitto_subscribe(mosq, &mid, topic, qos);
}
static void mosq_on_connect_callback(struct mosquitto *mosq, void *obj, int mid)
{
int ret = 0;
// for (int i = 0; i < ARR_SIZE(topic); i++)
// {
// if ((ret = mosquitoto_subscribe_topic(topic[i], i, mid)) == MOSQ_ERR_SUCCESS) //订阅主题
// {
// printf("subscribe success\n");
// }
// else
// {
// fprintf(stderr, "subscribe failed %d\n", ret);
// }
// }
// if ((ret = mosquitoto_subscribe_topic("aaa", 0, 2)) == MOSQ_ERR_SUCCESS) //订阅主题
// {
// printf("subscribe success\n");
// }
// else
// {
// fprintf(stderr, "subscribe failed %d\n", ret);
// }
}
static void mosq_on_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{
printf("publish message");
}
static void mosq_on_subscribe_callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
}
static void mosquitto_mqtt_init(char *host, int port, int keepalive)
{
mosquitto_lib_init(); //初始化mosquitto库
mosq = mosquitto_new(NULL, true, NULL); //创建一个mosquitto实例
if (mosq == NULL)
{
mosquitto_lib_cleanup();
printf("create mosquitto obj failed\r\n");
exit(1);
}
mosquitto_connect_callback_set(mosq, mosq_on_connect_callback); //设置连接成功回到函数
mosquitto_publish_callback_set(mosq, mosq_on_publish_callback); //设置发布成功回调函数
mosquitto_subscribe_callback_set(mosq, mosq_on_subscribe_callback); //设置订阅请求成功回调函数
int retries = 0;
//return val MOSQ_ERR_SUCCESS
while (mosquitto_connect(mosq, host, port, keepalive) != MOSQ_ERR_SUCCESS && retries < 5) //如果连接失败,尝试重复连接5次
{
retries++;
}
if (retries >= 5)
{
printf("connect mqtt broker failed\n");
mosquitto_destroy(mosq); //连接失败销毁
exit(1);
}
printf("connect mqtt broker\r\n");
}
int mosquitto_publish_msg(const char * topic, int payloadlen, const void *payload, int mid, int qos)
{
return mosquitto_publish(mosq, &mid, topic, payloadlen, payload, qos, false);
}
void publish_msg_handler(top_sel_t select, char *msg)
{
int mid;
switch (select)
{
case TOPIC_LED:
{
mid = TOPIC_LED;
break;
}
case TOPIC_FAN:
{
mid = TOPIC_FAN;
break;
}
case TOPIC_CURTAIN:
{
mid = TOPIC_CURTAIN;
break;
}
}
printf("select topic :%s\n", topic[mid]);
printf("send message : %s\n", msg);
mosquitto_publish_msg(topic[mid], strlen(msg), msg, mid, 2);
}
int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: %s <host_ip>\r\n", argv[0]);
exit(1);
}
char *host = argv[1];
int port = MQTT_PORT;
int keepalive = 30;
mosquitto_mqtt_init(host, port, keepalive);
if (mosquitto_loop_start(mosq) != MOSQ_ERR_SUCCESS)
{
printf("failed to Call this once to start a new thread to process network traffic\n");
mosquitto_destroy(mosq); //连接失败销毁
mosquitto_lib_cleanup();
exit(1);
}
int select = 0;
char msg[1024] = {
0};
sleep(1);
while (1)
{
printf("please select topic, 0 - led 1 - fan 2 - curtain : ");
scanf("%d", &select);
printf("please input message to send:");
scanf("%s", msg);
publish_msg_handler((top_sel_t)select, msg);
}
return 0;
}
测试:
MQTT协议的发布者也可以是订阅者,只要发布者也订阅主题就可以实现双向通信,所以MQTT还能用在进程间通信。。。