上一篇文章简单提及了以异步函数和同步函数对比,由于异步函数是非阻塞的,所以性能上比同步函数要稍好些,所以也就常用异步函数来实现MQTT的通讯。
异步函数与同步函数两者的差别就是在连接服务器的connect函数、loop循环函数。那接下来就简单探究一下loop函数的调用方式:同步函数是调用mosquitto_loop函数来阻塞等待实现的一种通信;而查看源码我们就会发现,异步方式的"loop"函数就是创建了一个线程去完成同步方式中导致阻塞等待的mosquitto_loop函数,其调用过程如下:
mosquitto_loop_start(mosq); // 异步方式的loop
pthread_create(&mosq->thread_id, NULL, mosquitto__thread_main, mosq)
mosquitto_loop_forever(mosq, 1000*86400, 1);
mosquitto_loop(mosq, timeout, max_packets); // 同步方式的loop
mosquitto_loop_stop(mosq, false);
pthread_cancel(mosq->thread_id);
pthread_join(mosq->thread_id, NULL);
了解同步异步函数的调用区别之后,我们继续看一下异步方式连接服务器函数mosquitto_connect_async的官方说明:
Connect to an MQTT broker. This is a non-blocking call. If you use mosquitto_connect_async your client must use the threaded interface mosquitto_loop_start. If you need to use mosquitto_loop, you must use mosquitto_connect to connect the client.
May be called before or after mosquitto_loop_start.
现在我们可以根据connect函数与loop函数的匹配关系编写异步方式的通讯程序:
#include
#include
#include
#include
#include "mosquitto.h"
/* 设置打印开关 */
#define DEBUG_PROCESS printf
#define DEBUG_ERROR printf
#define DEBUG_MSG printf
// 定义运行标志决定是否需要结束
static int g_iRunFlag = 1;
/* 回调函数里添加自己的额外操作即可,mosquitto_xx函数已实现底层操作 */
void on_connect(struct mosquitto *mosq, void *obj, int rc);
void on_disconnect(struct mosquitto *mosq, void *obj, int rc);
void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos);
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg);
int main()
{
int ret;
struct mosquitto *mosq;
// 初始化mosquitto库
ret = mosquitto_lib_init();
if(ret){
DEBUG_ERROR("Init lib error!\n");
return -1;
}
// 创建一个实例
// 参数:id(不需要则为NULL)、clean_start、用户数据
mosq = mosquitto_new("Rookie_sub", true, NULL);
if(mosq == NULL){
DEBUG_ERROR("New error!\n");
mosquitto_lib_cleanup();
return -1;
}
// 设置连接的用户名与密码:,
// 参数:句柄、用户名、密码
ret = mosquitto_username_pw_set(mosq, "user_test", "123456");
if(ret){
DEBUG_ERROR("Set username and password error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
// 设置回调函数
// 参数:句柄、回调函数
mosquitto_connect_callback_set(mosq, on_connect);
mosquitto_disconnect_callback_set(mosq, on_disconnect);
mosquitto_subscribe_callback_set(mosq, on_subscribe);
mosquitto_message_callback_set(mosq, on_message);
// 连接至服务器
// 参数:句柄、ip(host)、端口、心跳
// ret = mosquitto_connect_async(mosq, "127.0.0.1", 2020, 60);
ret = mosquitto_connect_async(mosq, "127.0.0.1", 2020, 60);
if(ret){
DEBUG_ERROR("Connect server error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
ret = mosquitto_loop_start(mosq);
if(ret){
DEBUG_ERROR("Start loop error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
// 开始通信:循环执行、直到运行标志g_iRunFlag被改变
DEBUG_PROCESS("Start!\n");
while(g_iRunFlag)
{
//mosquitto_loop(mosq, -1, 1);
sleep(1);
}
// 结束后的清理工作
mosquitto_loop_stop(mosq, false);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
DEBUG_PROCESS("End!\n");
return 0;
}
void on_connect(struct mosquitto *mosq, void *obj, int rc)
{
DEBUG_PROCESS("Call the function: on_connect\n");
if(rc){
// 连接错误,退出程序
DEBUG_ERROR("on_connect error!\n");
exit(1);
}else{
// 订阅主题
// 参数:句柄、id、订阅的主题、qos
if(mosquitto_subscribe(mosq, NULL, "test/+", 2)){
DEBUG_ERROR("Set the topic error!\n");
exit(1);
}
}
}
void on_disconnect(struct mosquitto *mosq, void *obj, int rc)
{
DEBUG_PROCESS("Call the function: on_disconnect\n");
g_iRunFlag = 0;
}
void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
DEBUG_PROCESS("Call the function: on_subscribe\n");
}
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
DEBUG_PROCESS("Call the function: on_message\n");
DEBUG_MSG("Recieve a message: %s\n", (char *)msg->payload);
if(0 == strcmp(msg->payload, "quit")){
mosquitto_disconnect(mosq);
}
}
#include
#include
#include
#include
#include "mosquitto.h"
#define DEBUG_PROCESS printf
#define DEBUG_ERROR printf
#define DEBUG_MSG printf
static int g_iRunFlag = 1;
void on_connect(struct mosquitto *mosq, void *obj, int rc);
void on_disconnect(struct mosquitto *mosq, void *obj, int rc);
void on_publish(struct mosquitto *mosq, void *obj, int mid);
int main()
{
int ret;
struct mosquitto *mosq;
ret = mosquitto_lib_init();
if(ret){
DEBUG_ERROR("Init lib error!\n");
return -1;
}
mosq = mosquitto_new("Rookie_pub", true, NULL);
if(mosq == NULL){
DEBUG_ERROR("New error!\n");
mosquitto_lib_cleanup();
return -1;
}
// 设置MQTT遗言信息
// 参数:句柄、主题、消息长度、消息内容、qos、是否保留
ret = mosquitto_will_set(mosq, "test/will", strlen("pub_will_message"), "pub_will_message", 2, false);
if(ret){
DEBUG_ERROR("Set will message error!\n");
return -1;
}
ret = mosquitto_username_pw_set(mosq, "user_test", "123456");
if(ret){
DEBUG_ERROR("Set username and password error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
mosquitto_connect_callback_set(mosq, on_connect);
mosquitto_disconnect_callback_set(mosq, on_disconnect);
mosquitto_publish_callback_set(mosq, on_publish);
ret = mosquitto_loop_start(mosq);
if(ret){
DEBUG_ERROR("Start loop error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
// ret = mosquitto_connect(mosq, "127.0.0.1", 2020, 60);
ret = mosquitto_connect_async(mosq, "127.0.0.1", 2020, 60);
if(ret){
DEBUG_ERROR("Connect server error!\n");
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
return -1;
}
DEBUG_PROCESS("Start!\n");
while(g_iRunFlag)
{
//mosquitto_loop(mosq, -1, 1);
sleep(1);
}
mosquitto_loop_stop(mosq, false);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
DEBUG_PROCESS("End!\n");
return 0;
}
void on_connect(struct mosquitto *mosq, void *obj, int rc)
{
DEBUG_PROCESS("Call the function: on_connect\n");
if(rc){
DEBUG_ERROR("on_connect error!\n");
exit(1);
}else{
// 参数:句柄、id、主题、消息长度、消息、Qos、是否保留
if(mosquitto_publish(mosq, NULL, "test/common", strlen("hello"), "hello", 2, false)){
DEBUG_ERROR("Set the topic error!\n");
exit(1);
}
}
}
void on_disconnect(struct mosquitto *mosq, void *obj, int rc)
{
DEBUG_PROCESS("Call the function: on_disconnect\n");
g_iRunFlag = 0;
}
void on_publish(struct mosquitto *mosq, void *obj, int mid)
{
DEBUG_PROCESS("Call the function: on_publish\n");
sleep(2);
mosquitto_disconnect(mosq);
}