mosquitto 客户端源码剖析 mosquitto_loop_start()

29 篇文章 0 订阅

mosquitto 调用形式

源码
MainServer.h

#ifndef _WJ_MAINSERVER_H
#define _WJ_MAINSERVER_H

#include <event.h>
#include <mosquitto.h>

class MainServer{
public:
    // single
    static MainServer& getInstance(){
        static MainServer root;
        return root;
    }
    ~MainServer();
    void service_loop();

private:
    MainServer();
    void init( );

private:
    struct event_base * base_;
    struct event *      stdin_;
    struct mosquitto *  mqtt_;

private:
    static void stdinCB(evutil_socket_t socket, short what, void *arg);
};

#endif

MainServer.cpp

#include "MainServer.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <string>

// 连接回调函数,当连接成功时会进入这里,可以在这里进行连接成功之后的操作,比如连接之后的信息同步
void my_connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
    printf("connect cb\n");
}
// 断开连接回调函数,在断开连接之后进入
void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result)
{
    printf("disconnect cb\n");
}
// 发布消息回调函数
void my_publish_callback(struct mosquitto *mosq, void *obj, int mid)
{
    printf("publish cb\n");
}

void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str){
    printf("log callback: level[%d] str[%s]\n",level,str);
    
}

void my_subscribe_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
    std::string message((char *)(msg->payload),msg->payloadlen);
    printf("subscribe cb:[%s]\n",message.c_str());
}

MainServer::MainServer()
    :mqtt_(NULL){
    base_ = event_base_new();
    init();
}

MainServer::~MainServer(){
    printf("析构函数...\n");
    if(mqtt_ != NULL){
        mosquitto_loop_stop(mqtt_,true);
        mosquitto_destroy(mqtt_);
    }
    event_free(stdin_);
    event_base_free(base_);
}

void
MainServer::service_loop(){
    stdin_ = event_new(base_, STDIN_FILENO, EV_READ | EV_PERSIST, stdinCB, this);
    event_add(stdin_, NULL);
    event_base_dispatch(base_);
}

void MainServer::init(){
    mqtt_ = mosquitto_new("wanjun",true,NULL);

    mosquitto_connect_callback_set(mqtt_, my_connect_callback);
    mosquitto_disconnect_callback_set(mqtt_, my_disconnect_callback);
    mosquitto_publish_callback_set(mqtt_, my_publish_callback);
    mosquitto_message_callback_set(mqtt_, my_subscribe_callback);
    mosquitto_log_callback_set(mqtt_,my_log_callback);

    int err = mosquitto_connect(mqtt_,"localhost",1883,60);
    if(err == MOSQ_ERR_SUCCESS){
        printf("mosquitto connect successful\n");
    }

    mosquitto_subscribe(mqtt_,NULL,"wanjun_topic",0);
    
    // 非阻塞式的循环
    err = mosquitto_loop_start(mqtt_);
    if(err == MOSQ_ERR_SUCCESS){
        printf("mosquitto loop start successful\n");
    }
}

// STATIC
void
MainServer::stdinCB(evutil_socket_t fd, short what, void *arg){
    MainServer *server = (MainServer*)arg;

    char recvline[80];
    bzero(recvline,sizeof(recvline));
    ssize_t size = read(fd, recvline, sizeof(recvline));
    recvline[size-1] = '\0';
    printf("you have input cmd : [%s] \n", recvline);
    if( strncmp(recvline,"over",4) == 0){
        event_base_loopbreak(server->base_);
    }
}

class MainServer 使用了 libevent 库,完成一个简单的控制台输入输出指令。
我们的将目标放在一下的 code 上。

    mqtt_ = mosquitto_new("wanjun",true,NULL);

    mosquitto_connect_callback_set(mqtt_, my_connect_callback);
    mosquitto_disconnect_callback_set(mqtt_, my_disconnect_callback);
    mosquitto_publish_callback_set(mqtt_, my_publish_callback);
    mosquitto_message_callback_set(mqtt_, my_subscribe_callback);
    mosquitto_log_callback_set(mqtt_,my_log_callback);

    int err = mosquitto_connect(mqtt_,"localhost",1883,60);
    if(err == MOSQ_ERR_SUCCESS){
        printf("mosquitto connect successful\n");
    }

    mosquitto_subscribe(mqtt_,NULL,"wanjun_topic",0);
    
    // 非阻塞式的循环
    err = mosquitto_loop_start(mqtt_);
    if(err == MOSQ_ERR_SUCCESS){
        printf("mosquitto loop start successful\n");
    }

该程序目的很简单,就是创建一个 mosquitto 客户端,并且设置好相应的回调函数。调用 connect 连接到 mqtt broker 后,就可以异步接受来自 broker 的 message。
事实上 我们调用的 mosquitto_loop_start(mqtt_) 函数,是在 mosquitto 内部起了一个新的线程用于 message 的接受,当内部的线程接收到 message 后再调用回调函数。
为了证明这一实现,我们使用 htop 查看

  1. 不使用 init() 函数情况下,不适用 mosquitto 客户端
    在这里插入图片描述
  2. 使用 init() 函数的情况下
    在这里插入图片描述
    可以明显得出结论,mosquitto 中 mosquitto_loop_start() 函数内部实现是新起了一个线程用于阻塞式接受来自 broker 的 message,然后调用回调函数使得外部以一种异步形式处理 mqtt 业务。

Makefile

.PHONY: all

CXX = g++ -g -std=c++11
LDFLAGS = -lmosquittopp -lmosquitto -levent

all: server wj-mosquitto wj-mosquitto2

server: server.o
	$(CXX) $^ $(LDFLAGS) -o $@ 

wj-mosquitto: client.o MainServer.o TMqttWrapper.o
	$(CXX) $^ $(LDFLAGS) -o $@ 

wj-mosquitto2: client2.o
	$(CXX) $^ $(LDFLAGS) -o $@ 

clean:
	rm -rf server wj-mosquitto wj-mosquitto2 *.o core

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值