上一篇文章已經將mosquitto移植到了arm平臺上,現在將使用mosquitto完成mqtt客服端的demo,瞭解過mqtt協議的小夥伴都知道,mqtt主要分為代理伺服器、釋出者、訂閱者三部分。接下來通過mqtt釋出者和訂閱者兩個demo瞭解mosquitto庫函式的使用。

一、Mosquitto庫函式的API

mosquitto的api說明文件:https://mosquitto.org/api/files/mosquitto-h.html

mosquitto庫中常見的函式應用總結:https://blog.csdn.net/makunIT/article/details/107283260

上面這位博主總結的比較好,我就在這裡引用一下,需要的小夥伴可以看看。

二、mqtt釋出者原始碼

mqtt_pub_demo.c

#include <stdio.h>
#include <stdlib.h>
#include <mosquitto.h>
#include <string.h> #define HOST "192.168.2.99"
#define PORT 1883
#define KEEP_ALIVE 60
#define MSG_MAX_SIZE 512 bool session = true; int main(void)
{ int err = 0; printf("mqtt publish init...\n");
struct mosquitto *mosq = NULL;
char buff[MSG_MAX_SIZE]; //libmosquitto 庫初始化
err = mosquitto_lib_init();
if (err < 0){
printf("mosquitto lib int fail...");
goto fail_mosquitto_lib;
} //建立mosquitto客戶端
mosq = mosquitto_new(NULL,session,NULL);
if (mosq == NULL){
printf("create client failed...\n");
err = -1;
goto fail_mosquitto_new;
} //客戶端連線伺服器
err = mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE);
if (err < 0){
printf("connect fail");
goto fail_mosq_conn;
} //不阻塞,庫函式中將自動建立執行緒實現
err = mosquitto_loop_start(mosq);
if(err != MOSQ_ERR_SUCCESS){
printf("mosquitto loop error\n");
goto fail_mosq_loop_start;
} while(fgets(buff, MSG_MAX_SIZE, stdin) != NULL)
{
mosquitto_publish(mosq, NULL, "temp", strlen(buff)+1, buff, 0, 0);
memset(buff, 0, sizeof(buff));
} mosquitto_disconnect(mosq);
mosquitto_loop_stop(mosq, true);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup(); return 0;
fail_mosq_loop_start:
mosquitto_disconnect(mosq);
fail_mosq_conn:
mosquitto_destroy(mosq);
fail_mosquitto_new:
mosquitto_lib_cleanup();
fail_mosquitto_lib:
return err;
}

Makefile

INCLUDES = -lmosquitto -lpthread -ldl -lssl -lcrypto  \
-I/home/linux/arm-lib/mosquitto/include \
-L/home/linux/arm-lib/mosquitto/lib \
-L/homelinux/arm-lib/openssl/lib SOURCE = $(wildcard ./*.c) OBJ = $(patsubst ./%.c, ./%.0, $(SOURCE)) #INCLUDES = $(wildcard ./*.h) TARGET = mqtt_pub_demo
CC = arm-linux-gnueabihf-gcc $(TARGET):$(OBJ)
$(CC) $(OBJ) -o $(TARGET) $(INCLUDES) %.0:%.c
$(CC) -c $< -o $@ $(INCLUDES) clean:
rm -rf $(OBJ) $(TARGET)

三、mqtt訂閱者原始碼

mqtt_sub_demo.c

#include <stdio.h>
#include <stdlib.h>
#include <mosquitto.h>
#include <string.h> #define HOST "192.168.2.99"
#define PORT 1883
#define KEEP_ALIVE 60 bool session = true; void mqtt_subscribe_callback(struct mosquitto *mosq,
void *userdata, int mid, int qos_count, const int *granted_qos)
{
int i;
printf("subscribed (mid: %d): %d", mid, granted_qos[0]);
for(i=1; i < qos_count; i++){
printf(", %d", granted_qos[i]);
}
printf("\n");
} //訊息回撥函式,收到訂閱的訊息後呼叫
void mqtt_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
if (message->payloadlen){
printf("%s %s \n", message->topic, (char *)message->payload);
}else{
printf("%s (null)\n",message->topic);
}
} //mqtt連接回調
void mqtt_connect_callback(struct mosquitto *mosq, void *userdata, int result)
{
int ret;
if (!result){
ret = mosquitto_subscribe(mosq, NULL, "temp", 2);
if(ret < 0){
printf("Subscription failed\n");
}else{
printf("Subscription succeeded\n");
}
}else{
printf("connect failed\n");
}
} //日誌回撥函式
void mqtt_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)
{
printf("log__ %s\n", str);
} int main(void)
{ int err = 0;
printf("mqtt client init...\n"); struct mosquitto *mosq = NULL; //libmosquitto 庫初始化
err = mosquitto_lib_init();
if (err < 0){
printf("mosquitto lib int fail...");
goto fail_mosquitto_lib;
} //建立mosquitto客戶端
mosq = mosquitto_new(NULL,session,NULL);
if (mosq == NULL){
printf("create client failed...\n");
err = -1;
goto fail_mosquitto_new;
} //設定回撥函式
mosquitto_log_callback_set(mosq, mqtt_log_callback);
mosquitto_connect_callback_set(mosq, mqtt_connect_callback);
mosquitto_message_callback_set(mosq, mqtt_message_callback);
mosquitto_subscribe_callback_set(mosq, mqtt_subscribe_callback); //客戶端連線伺服器
err = mosquitto_connect(mosq, HOST, PORT, KEEP_ALIVE);
if (err < 0){
printf("connect fail");
goto fail_mosq_conn;
} //主線成將被阻塞至此
err = mosquitto_loop_forever(mosq, -1, 1);
if (err < 0){
printf("mosquitto loop fail");
goto fail_mosq_loop_stop;
} mosquitto_disconnect(mosq);
mosquitto_loop_stop(mosq, false);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup(); return 0; fail_mosq_loop_stop:
mosquitto_disconnect(mosq);
fail_mosq_conn:
mosquitto_destroy(mosq);
fail_mosquitto_new:
mosquitto_lib_cleanup();
fail_mosquitto_lib:
return err; }

Makefile

INCLUDES = -lmosquitto -lpthread -ldl -lssl -lcrypto  \
-I/home/xfg/linux/arm-lib/mosquitto/include \
-L/home/xfg/linux/arm-lib/mosquitto/lib \
-L/home/xfg/linux/arm-lib/openssl/lib SOURCE = mqtt_sub_demo.c TARGET = mqtt_sub_demo
CC = arm-linux-gnueabihf-gcc $(TARGET):$(SOURCE)
$(CC) $(SOURCE) -o $(TARGET) $(INCLUDES) clean:
rm -rf $(TARGET)

四、測試

  1. 在虛擬機器上開啟代理伺服器,並將編譯生成的mqtt_sub_demo和mqtt_pub_demo移動到ARM開發版上

  2. 開啟mqqt訂閱者

  3. 開啟mqtt釋出者,釋出資訊



    完成後,可以看訂閱者接受的資訊是否正確



    由此可以看出編寫的測試程式沒問題。

五、參考文獻

mosquitto庫中常見的函式應用總結:https://blog.csdn.net/makunIT/article/details/107283260

基於MQTT協議的Mosquitto的使用及libmosquitto客戶端程式設計:https://blog.csdn.net/danwuxie/article/details/86517568

基於mosquitto的MQTT客戶端實現C語言:https://www.cnblogs.com/y-c-y/p/11686916.html

Qt官方MQTT庫的使用,附一個MqttClient例子:https://www.cnblogs.com/yexiaopeng/p/8542894.html

mosquitto的api說明文件:https://mosquitto.org/api/files/mosquitto-h.html