MQTT通信时,使用发布/订阅消息模式,其通信模型如下:
在编写客户端程序时,需要准备好服务器(broker)的ip地址和端口号。
获取 ip地址:
1 如果是本地服务器,ip地址设为localhost即可。
2 通过ipconfig指令查看ip地址
$ ipconfig
ens33: flags=4163 mtu 1500
inet 192.168.0.109 netmask 255.255.255.0 broadcast 192.168.0.255
..........
io地址为:192.168.0.109
端口号:默认服务器监听的端口是1883
int res = 0;
res = mosquitto_lib_init();
if(res < 0)
{
std::cout<<"mosquitto_lib_init()失败"<<std::endl;
return;
}
Mosq *pub_mosq = NULL;
pub_mosq = mosquitto_new(NULL,session,NULL);
if(pub_mosq == NULL)
{
std::cout<<"mosquitto_new()失败"<<std::endl;
mosquitto_lib_cleanup();
return;
}
char HOST[] = "localhost";
int PORT = 1883 ;
int KEPP_LIVE = 10;
if(mosquitto_connect(pub_mosq,HOST,PORT,KEPP_LIVE)
{
std::cout<<"mosquitto_connect()失败"<<std::endl;
mosquitto_destroy(pub_mosq);
mosquitto_lib_cleanup();
return;
}
int res;
res = mosquitto_loop_start(pub_mosq);
if(res != MOSQ_ERR_SUCCESS)
{
std::cout<<"mosquitto_loop_start()失败"<<std::endl;
return;
}
int *mid =NULL; //消息的id
char topic[] = "temp";
char buffer[MSG_MAX_SIZE];
int len = strlen(buffer)+1;
int qos = 0;
bool retain = false;//是否保留消息
mosquitto_publish(pub_mosq,mid,topic,len,buffer,qos,retain);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
#include
#include
//#include
//#include
#include
#define HOST "localhost" //连接本地服务器broker
#define PORT 1883 //端口号
#define KEPP_LIVE 10
#define MSG_MAX_SIZE 512
bool session = true;
typedef struct mosquitto Mosq;
int main()
{
int res = 0;
char buffer[MSG_MAX_SIZE];
Mosq *pub_mosq = NULL;
//libmosquitto 库初始化
res = mosquitto_lib_init();
if(res < 0)
{
std::cout<<"mosquitto_lib_init()失败"<<std::endl;
return 1;
}
//创建发布者客户端实例
pub_mosq = mosquitto_new(NULL,session,NULL);
if(pub_mosq == NULL)
{
std::cout<<"mosquitto_new()失败"<<std::endl;
mosquitto_lib_cleanup();
return 1;
}
// 连接服务器:ip地址、端口号、保持连接的时间间隔
if(mosquitto_connect(pub_mosq, HOST,PORT,KEPP_LIVE) )
{
std::cout<<"mosquitto_connect()失败"<<std::endl;
mosquitto_destroy(pub_mosq);
mosquitto_lib_cleanup();
return 1;
}
// 开启线程,处理网络信息
res = mosquitto_loop_start(pub_mosq);
if(res != MOSQ_ERR_SUCCESS)
{
std::cout<<"mosquitto_loop_start()失败"<<std::endl;
return 1;
}
//发布消息:话题名、负载、Qos
while(fgets(buffer,MSG_MAX_SIZE,stdin) != NULL)
{
int *mid = NULL;
mosquitto_publish(pub_mosq,mid,"temp",strlen(buffer)+1,buffer,0,0);
memset(buffer,0,sizeof(buffer));
}
//销毁发布者客户端,清除libmosquitto 库
mosquitto_destroy(pub_mosq);
mosquitto_lib_cleanup();
return 0;
}
订阅者客户端和发布者客户端在编写步骤上差不多,订阅者客户端在回调函数对话题消息进行处理。
int res = 0;
res = mosquitto_lib_init();
if(res < 0)
{
std::cout<<"mosquitto_lib_init()失败"<<std::endl;
return ;
}
Mosq *mosq = NULL;
mosq = mosquitto_new(NULL,session,NULL);
if(mosq == NULL)
{
std::cout<<"mosquitto_new()失败"<<std::endl;
mosquitto_lib_cleanup();
return ;
}
//建立连接后,订阅话题的回调函数
void mqtt_connect_calllback(Mosq *mosq,void *userdata, int result)
{
int ret;
if(!result)
{
ret = mosquitto_subscribe(mosq, NULL ,"temp",2);
if(ret <0)
{
std::cout<<"订阅失败"<<std::endl;
}
else
{
std::cout<<"订阅成功"<<std::endl;
}
}
else
{
std::cout<<"订阅者连接失败"<<std::endl;
}
}
//订阅成功后的回调函数
void mqtt_subscriber_callback(Mosq *mosq, void *userdata,int mid,int qos_count,const int *granted_qos)
{
int i;
std::cout<<"订阅者(消息的id是: "<<mid<<"}:"<<granted_qos[0];
for(int i=0; i< qos_count;i++)
{
std::cout<<granted_qos[0]<<std::endl;
}
}
//消息送达时的回调函数
void mqtt_message_callback(Mosq *mosq,void *userdata,const struct mosquitto_message *message)
{
if(message->payloadlen)
{
printf("订阅的消息的话题:%s \n", message->topic, (char *)message->payload);
}
else
{
std::cout<<"话题的负载(内容):%s \n"<<message->payload<<std::endl;
}
}
//断开连接时的回调函数
void my_disconnect_callback(Mosq *mosq,void *obj,int rc)
{
std::cout<<"断开连接"<<std::endl;
running = 0;
}
//日志回调函数
void mqtt_log_callback(Mosq *mosq ,void *userdata,int level,const char*str)
{
std::cout<<"日志级别"<<level<<":"<<str<<std::endl;
}
// 设置回调函数
mosquitto_connect_callback_set(sub_mosq,mqtt_connect_calllback);
mosquitto_subscribe_callback_set(sub_mosq,mqtt_subscriber_callback);
mosquitto_message_callback_set(sub_mosq,mqtt_message_callback);
mosquitto_disconnect_callback_set(sub_mosq,my_disconnect_callback);
mosquitto_log_callback_set(sub_mosq,mqtt_log_callback);
if(mosquitto_connect(mosq,HOST,PORT,KEEP_LIVE))
{
std::cout<<"mosquitto_connect()失败"<<std::endl;
return 1;
}
static int running = 1;
while(running)
{
mosquitto_loop(mosq,-1,1);
}
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
#include
#include
#define HOST "localhost"
#define PORT 1883
#define KEEP_LIVE 60
bool session = true; //?为什么要设计成全局变量
typedef struct mosquitto Mosq;
static int running = 1;
//建立连接后,订阅话题的回调函数
void mqtt_connect_calllback(Mosq *mosq,void *userdata, int result)
{
int ret;
if(!result)
{
ret = mosquitto_subscribe(mosq, NULL ,"temp",2);
if(ret <0)
{
std::cout<<"订阅失败"<<std::endl;
}
else
{
std::cout<<"订阅成功"<<std::endl;
}
}
else
{
std::cout<<"订阅者连接失败"<<std::endl;
}
}
//订阅成功后的回调函数
void mqtt_subscriber_callback(Mosq *mosq, void *userdata,int mid,int qos_count,const int *granted_qos)
{
int i;
std::cout<<"订阅者(消息的id是: "<<mid<<"}:"<<granted_qos[0];
for(int i=0; i< qos_count;i++)
{
std::cout<<granted_qos[0]<<std::endl;
}
}
//消息送达时的回调函数
void mqtt_message_callback(Mosq *mosq,void *userdata,const struct mosquitto_message *message)
{
if(message->payloadlen)
{
printf("订阅的消息的话题:%s \n 话题的负载:%s \n", message->topic, (char *)message->payload);
}
else
{
std::cout<<"订阅的消息的话题:"<<message->payload<<std::endl;
}
}
//断开连接时的回调函数
void my_disconnect_callback(Mosq *mosq,void *obj,int rc)
{
std::cout<<"断开连接"<<std::endl;
running = 0;
}
//日志回调函数
void mqtt_log_callback(Mosq *mosq ,void *userdata,int level,const char*str)
{
std::cout<<"日志级别"<<level<<":"<<str<<std::endl;
}
int main()
{
int res = 0;
std::cout<<"mosq 订阅者初始化"<<std::endl;
Mosq *sub_mosq = NULL;
//libmosquitto 库初始化
res = mosquitto_lib_init();
if(res < 0)
{
std::cout<<"mosquitto_lib_init()失败"<<std::endl;
mosquitto_lib_cleanup();
return 1;
}
//创建客户端实例
sub_mosq = mosquitto_new(NULL,session,NULL);
if(!sub_mosq)
{
std::cout<<"mosquitto_new()失败"<<std::endl;
mosquitto_lib_cleanup();
return 1;
}
// 设置回调函数
mosquitto_connect_callback_set(sub_mosq,mqtt_connect_calllback);
mosquitto_subscribe_callback_set(sub_mosq,mqtt_subscriber_callback);
mosquitto_message_callback_set(sub_mosq,mqtt_message_callback);
mosquitto_disconnect_callback_set(sub_mosq,my_disconnect_callback);
mosquitto_log_callback_set(sub_mosq,mqtt_log_callback);
//连接服务器:ip地址,端口号,保持连接的时间间隔
if(mosquitto_connect(sub_mosq,HOST,PORT,KEEP_LIVE))
{
std::cout<<"mosquitto_connect()失败"<<std::endl;
return 1;
}
while(running)
{
mosquitto_loop(sub_mosq,-1,1);
}
mosquitto_destroy(sub_mosq);
mosquitto_lib_cleanup();
return 0;
}
Makefile文件
all:Subscriber Publiser
@echo ""
@echo "Start compiling"
@echo ""
Subscriber:
@g++ -o Subscriber mqtt_sub.cpp -lmosquitto -lpthread -ldl -lssl -lcrypto
Publiser:
@g++ -o Publisher mqtt_pub.cpp -lmosquitto -lpthread -ldl -lssl -lcrypto
clean:
-rm Publiser Subscriber
打开一终端,启动mosquitto服务器
$ mosquitto -v
另起一终端,运行订阅者
$ ./Subscriber
再起一终端,运行发布者
$./Publisher