谷谷小师妹 发表于 2023-11-20 23:38:14

使用Mosquitto实现MQTT客户端C语言

使用Mosquitto实现MQTT客户端C语言




  上一篇文章已经将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 PORT1883
#define KEEP_ALIVE 60
#define MSG_MAX_SIZE512

bool session = true;

int main(void)
{

    int err = 0;

    printf("mqtt publish init...\n");
    struct mosquitto *mosq = NULL;
    char buff;

    //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;
}
MakefileINCLUDES = -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 [      DISCUZ_CODE_15      ]lt; -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 PORT1883
#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);
    for(i=1; i < qos_count; i++){
      printf(", %d", granted_qos);
    }
    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;
}
MakefileINCLUDES = -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)

四、测试
[*]在虚拟机上打开代理服务器,并将编译生成的mqtt_sub_demo和mqtt_pub_demo移动到ARM开发版上

[*]打开mqqt订阅者

[*]打开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
页: [1]
查看完整版本: 使用Mosquitto实现MQTT客户端C语言