mqtt客户端linux,基于mosquitto的MQTT客户端实现C语言

在对mqtt的学习过程中 一下的内容对我提供了帮助

https://www.runoob.com/w3cnote/mqtt-intro.html 对mqtt的入门级介绍 很基础讲解了什么是mqtt

https://mosquitto.org/api/files/mosquitto-h.html 这个网站记载了几乎所有的mosquitto的接口 你想知道的函数接口他都有 函数简介可能看不出来什么 点进去看一下详细解释还是很清晰的

以下的图片能够更加直观地说明mqtt协议的通信方式

25bc5ed3210f6a8bae2af3f44881d403.png

3dc8337487cd103e3de37993e0fecf78.png

根据这两张图片谈一下我对mqtt的了解:

在mqtt协议中 运行了broker的才算是真正的服务器 它掌控着所有消息的publish和subscribe 而他的客户端程序可以有一下三重情况

1.运行了publisher的程序 做着publish的工作

2.运行了subscriber的程序 做着subscribe的工作

3.运行了subscriber和publisher的程序 既可以publish也可以subscribe 这并不意味着这样的程序就是broker

这三种情况你可以根据自己实际的需要来确定自己的客户端可以是哪一种

例如你的客户端仅仅是需要收到来自broker的topic为"ycy"的消息然后解析处理 并不需要做任何的publish工作 那么你就可以选择第2种客户端

我的程序的功能是从云端得到固定topic的消息之后就开始处理这个消息 处理完成后publish出去 由于我在linux机上 我必须做一个仿broker来实现从云端得到消息这一步

首先我的预想是这样的

45fcb60ccdb6717236a85c20fabbad82.png

但是这样就会导致我每次publish出去数据 我自己又会收到一份 这样的话我又会再次扫描这个数据 以确定是不是需要解析处理 万一的情况恰好是约定的需要解析的字符(这就误会大了)

所以 在我这里没有使用同一个topic 其实还有解决方法二(下文再说)

cb0f0d2c9b1e9a9479e020062f82fe77.png

解决方法二:

就是在my_message_callback这个函数中过滤一下 将自己publish的topic过滤一下(在我下面的代码中并没有实现 只是提供这样的思路 strcmp函数可以帮到很多)

mqtt_server.c

#include

#include

#include

#include

#define host "localhost"

#define port 1883

#define keep_alive 60

#define msg_max_size 512

#define topic_num 3

bool session = true;

const static char* topic[topic_num] =

{

"gai爷:",

"ycy ",

"ccyy "

};

void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)

{

if(message->payloadlen){

printf("%s %s", message->topic, (char *)message->payload);

}else{

printf("%s (null)\n", message->topic);

}

fflush(stdout);

}

void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)

{

int i;

if(!result){

/* subscribe to broker information topics on successful connect. */

mosquitto_subscribe(mosq, null, "ccyy ", 2);

}else{

fprintf(stderr, "connect failed\n");

}

}

void my_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

printf(", %d", granted_qos[i]);

}

printf("\n");

}

void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)

{

/* pring all log messages regardless of level. */

printf("%s\n", str);

}

int main()

{

struct mosquitto *mosq = null;

char buff[msg_max_size];

//libmosquitto 库初始化

mosquitto_lib_init();

//创建mosquitto客户端

mosq = mosquitto_new(null,session,null);

if(!mosq){

printf("create client failed..\n");

mosquitto_lib_cleanup();

return 1;

}

//设置回调函数,需要时可使用

mosquitto_log_callback_set(mosq, my_log_callback);

mosquitto_connect_callback_set(mosq, my_connect_callback);

mosquitto_message_callback_set(mosq, my_message_callback);

mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);

//连接服务器

if(mosquitto_connect(mosq, host, port, keep_alive)){

fprintf(stderr, "unable to connect.\n");

return 1;

}

//开启一个线程,在线程里不停的调用 mosquitto_loop() 来处理网络信息

int loop = mosquitto_loop_start(mosq);

if(loop != mosq_err_success)

{

printf("mosquitto loop error\n");

return 1;

}

while(fgets(buff, msg_max_size, stdin) != null)

{

/*发布消息*/

mosquitto_publish(mosq,null,"ycy ",strlen(buff)+1,buff,0,0);

memset(buff,0,sizeof(buff));

}

mosquitto_destroy(mosq);

mosquitto_lib_cleanup();

return 0;

}

mqtt_client.c

#include

#include

#include

#include

#define host "localhost"

#define port 1883

#define keep_alive 60

#define msg_max_size 512

#define topic_num 3

bool session = true;

const static char* topic[topic_num] =

{

"gai爷:",

"ycy ",

"ccyy "

};

void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)

{

if(message->payloadlen){

printf("%s %s", message->topic, (char *)message->payload);

}else{

printf("%s (null)\n", message->topic);

}

fflush(stdout);

}

void my_connect_callback(struct mosquitto *mosq, void *userdata, int result)

{

int i;

if(!result){

/* subscribe to broker information topics on successful connect. */

mosquitto_subscribe(mosq, null, "ycy ", 2);

}else{

fprintf(stderr, "connect failed\n");

}

}

void my_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

printf(", %d", granted_qos[i]);

}

printf("\n");

}

void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str)

{

/* pring all log messages regardless of level. */

printf("%s\n", str);

}

int main()

{

struct mosquitto *mosq = null;

char buff[msg_max_size];

//libmosquitto 库初始化

mosquitto_lib_init();

//创建mosquitto客户端

mosq = mosquitto_new(null,session,null);

if(!mosq){

printf("create client failed..\n");

mosquitto_lib_cleanup();

return 1;

}

//设置回调函数,需要时可使用

mosquitto_log_callback_set(mosq, my_log_callback);

mosquitto_connect_callback_set(mosq, my_connect_callback);

mosquitto_message_callback_set(mosq, my_message_callback);

mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);

//连接服务器

if(mosquitto_connect(mosq, host, port, keep_alive)){

fprintf(stderr, "unable to connect.\n");

return 1;

}

//开启一个线程,在线程里不停的调用 mosquitto_loop() 来处理网络信息

int loop = mosquitto_loop_start(mosq);

if(loop != mosq_err_success)

{

printf("mosquitto loop error\n");

return 1;

}

while(fgets(buff, msg_max_size, stdin) != null)

{

/*发布消息*/

mosquitto_publish(mosq,null,"ccyy ",strlen(buff)+1,buff,0,0);

memset(buff,0,sizeof(buff));

}

mosquitto_destroy(mosq);

mosquitto_lib_cleanup();

return 0;

}

makefile

#不是系统默认库 要记得添加连接选项

all:client

@echo ""

@echo "start compiling......"

@echo ""

client:server

gcc -o client mqtt_client.c -lmosquitto -lpthread

server:

gcc -o server mqtt_server.c -lmosquitto -lpthread

clean:

-rm server client

程序运行截图如下:

server

673f89df9b76d546dfe60ea5bccf090a.png

client

69362afb9d99ffca16827520f5e49a1a.png

以上

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值