C语言网络编程(5)— MQTT通信

2023-05-16

C语言网络编程(5)— MQTT通信

一、下载mqtt C语言库

首先我们要下载支持MQTT的C语言库,直接使用git命令拉取:

git clone https://github.com/eclipse/paho.mqtt.c.git

API文档介绍:http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/index.html
安装一些需要使用的库:

sudo apt-get install libssl-dev build-essential libidn11-dev libidn11

然后我们进入下载好的源码目录,使用make命令编译得到我们需要的库文件
在这里插入图片描述
然后我们可以在paho.mqtt.c/build/output下可以找到如下的输出文件:
在这里插入图片描述
这里面的各个动态库的作用:

paho-mqtt3a  : 一般实际开发中就是使用这个,a表示的是异步消息推送(asynchronous)。
paho-mqtt3as : as表示的是 异步+加密(asynchronous+OpenSSL)。
paho-mqtt3c  : c 表示的应该是同步(Synchronize),一般性能较差,是发送+等待模式。
paho-mqtt3cs : cs表示的是同步+加密(asynchronous+OpenSSL)。

然后我们使用make install则是将生成的库文件移动到系统路径之下。
在这里插入图片描述
在paho.mqtt.c/src/samples目录下有一些示例:
在这里插入图片描述

二、编写程序连接到MQTT服务器

首先包含需要用到的头文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"

然后宏定义一些连接mqtt服务器需要的参数:

#define MQTT_Uri    "tcp://39.96.35.207:1883"   // MQTT服务器的地址和端口号
#define ClientId    "ubuntu16"                  // ClientId需要唯一
#define username    "ubuntu16"                  // 用户名
#define password    "123456"                    // 用户名对应的密码

然后我们可以开始编写main()函数,
首先,定义一个MQTT客户端结构体指针,用来接收后面创建的MQTT客户端结构体

    // 1、定义一个MQTT客户端结构体指针
    MQTTClient client;

然后使用MQTTClient_create()函数创建一个MQTT客户端,创建成功后客户端结构体将赋值给client;

    // 2、创建一个MQTT客户端
    if ((rc = MQTTClient_create(&client, MQTT_Uri, ClientId, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
    {
         printf("Failed to create mqtt client, return code %d\n", rc);
         exit(EXIT_FAILURE);
    }

接下来准备连接用的结构体

    // 3、创建一个MQTT连接配置结构体,并配置其参数
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    conn_opts.username = UserName;          // 用户名 
    conn_opts.password = PassWord;          // 用户名对应的密码
    conn_opts.keepAliveInterval = 60;       // 心跳时间
    conn_opts.cleansession = 1;             // 清除会话

然后设置回调函数,

	// 4、设置MQTT连接时的回调函数
    MQTTClient_setCallbacks(client, NULL, connect_lost, message_arrived, delivery_complete);

失去连接的回调函数

// 失去连接回调函数
void connect_lost(void *context, char *cause)
{
    printf("Connection lost,The reason: %s \n",cause);
}

配置好之后就可以连接到MQTT服务器了

    // 5、开始连接到MQTT服务器
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

我们先让其延时10秒以便于我们观察

    sleep(10);

因为我们要用到动态库文件paho-mqtt3c.so,使用在编译的时候要加上参数-lpaho-mqtt3c,我们编译,运行
在这里插入图片描述
然后打开EMQ控制台可以看到,已经连接成功了
在这里插入图片描述

三、发布主题

连接成功后就可以发布主题了,首先定义一个用来存储主题消息的结构体,然后将配置成我们需要发送的消息

    // 6、定义一个主题消息存储结构体
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    char mag_data[] = "I am Ubuntu16.";
    pubmsg.payload = mag_data;
    pubmsg.payloadlen = (int)strlen(mag_data);
    pubmsg.qos = 1;                 // qos等级为1 
    pubmsg.retained = 0;            // 服务器不保留消息
    MQTTClient_deliveryToken token; // 标记MQTT消息的值,用来检查消息是否发送成功

    // 7、发布主题信息
    if ((rc = MQTTClient_publishMessage(client, "ubuntu16_publish", &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to publish message, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

然后实现主题发布成功的回调函数

// 主题发布成功回调函数
void delivery_complete(void *context, MQTTClient_deliveryToken dt)
{
    printf("publish topic success,token = %d \n", dt);
}

编译,运行代码,可以看到,发布消息成功:
在这里插入图片描述
使用MQTTfx来订阅ubuntu16_publish主题,可以收到消息:
在这里插入图片描述

四、订阅主题

接下来,我们订阅一个主题:

    // 8、订阅主题
    if ((rc = MQTTClient_subscribe(client, "ubuntu16_subscribe", 1)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        rc = EXIT_FAILURE;
    }

然后实现收到主题信息回调函数

// 收到主题信息回调函数
int message_arrived(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Receive topic: %s,message data: \n", topicName);
    printf("%.*s\n", message->payloadlen, (char*)message->payload);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

编译,运行,通过MQTTfx发布一个ubuntu16_subscribe主题消息,可以看到,接收到消息
在这里插入图片描述

四、代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "MQTTClient.h"

#define MQTT_Uri    "tcp://39.96.35.207:1883"   // MQTT服务器的地址和端口号
#define ClientId    "ubuntu16"                  // ClientId需要唯一
#define UserName    "ubuntu16"                  // 用户名
#define PassWord    "123456"                    // 用户名对应的密码

// 失去连接回调函数
void connect_lost(void *context, char *cause)
{
    printf("Connection lost,The reason: %s \n",cause);
}

// 收到主题信息回调函数
int message_arrived(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Receive topic: %s, message data: \n", topicName);
    printf("%.*s\n", message->payloadlen, (char*)message->payload);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

// 主题发布成功回调函数
void delivery_complete(void *context, MQTTClient_deliveryToken dt)
{
    printf("publish topic success,token = %d \n", dt);
}

int main(int argc, char* argv[])
{
    // 1、定义一个MQTT客户端结构体指针
    MQTTClient client;

    // 2、创建一个MQTT客户端
    int rc;
    if ((rc = MQTTClient_create(&client, MQTT_Uri, ClientId, MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to create client, return code %d\n", rc);
        exit(EXIT_FAILURE);
        goto exit;
    }

    // 3、创建一个MQTT连接配置结构体,并配置其参数
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    conn_opts.username = UserName;          // 用户名 
    conn_opts.password = PassWord;          // 用户名对应的密码
    conn_opts.keepAliveInterval = 60;       // 心跳时间
    conn_opts.cleansession = 1;             // 清除会话
    
    // 4、设置MQTT连接时的回调函数
    if ((rc = MQTTClient_setCallbacks(client, NULL, connect_lost, message_arrived, delivery_complete)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to set callbacks, return code %d\n", rc);
        rc = EXIT_FAILURE;
        goto destroy_exit;
    }

    // 5、开始连接到MQTT服务器
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
        goto destroy_exit;
    }

    // 6、定义一个主题消息存储结构体
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    char mag_data[] = "I am Ubuntu16.";
    pubmsg.payload = mag_data;
    pubmsg.payloadlen = (int)strlen(mag_data);
    pubmsg.qos = 1;                 // qos等级为1 
    pubmsg.retained = 0;            // 服务器不保留消息
    MQTTClient_deliveryToken token; // 标记MQTT消息的值,用来检查消息是否发送成功

    // 7、发布主题信息
    if ((rc = MQTTClient_publishMessage(client, "ubuntu16_publish", &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to publish message, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    // 8、订阅主题
    if ((rc = MQTTClient_subscribe(client, "ubuntu16_subscribe", 1)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        rc = EXIT_FAILURE;
    }

    // 9、等待输入'Q'或'q'退出
    printf("Press Q or q + <Enter> to quit\n\n");
    int ch;
    do
    {
            ch = getchar();
    } while (ch!='Q' && ch != 'q');

    if ((rc = MQTTClient_unsubscribe(client, "ubuntu16_subscribe")) != MQTTCLIENT_SUCCESS)
    {
            printf("Failed to unsubscribe, return code %d\n", rc);
            rc = EXIT_FAILURE;
    }

    // 10、断开连接
    if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to disconnect, return code %d\n", rc);
        rc = EXIT_FAILURE;
    }

destroy_exit:
    MQTTClient_destroy(&client);
exit:
    return rc;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言网络编程(5)— MQTT通信 的相关文章

随机推荐

  • ADC转换值和实际电压的关系

    1 首先确定ADC用几位表示 xff0c 最大数值是多少 比如一个8位的ADC xff0c 最大值是0xFF xff0c 就是255 xff08 一般芯片手册会有说明 xff09 2 然后确定最大值时对应的参考电压值 一般而言最大值对应3
  • 程序设置波特率和串口调试助手波特率设置不同才能通信

    本人小白一个 xff0c 在根据教程去做串口通信时 xff0c 程序码完之后 xff0c 调试助手一直显示乱码 网络上查找原因 xff0c 得知是波特率不对 xff0c 当串口的波特率是38400 xff0c 程序上是115200时 xff
  • MPC574x平台学习——CAN通信

    前言 MPC574x是恩智浦公司出的一个系列的芯片 xff0c 本人所接触的主要是MPC5742 xff0c 最近在调试MPC5742的CAN通信 xff0c 使用S32自带的SDK生成CAN驱动 通过网络的教程去完成 xff0c 但是跟着
  • QT报错:error: static assertion failed: No Q_OBJECT in the class with the signal

    今天利用QT写一个项目 xff0c 在写代码的过程中 xff0c 使用到了QT中一大特色 信号和槽 xff0c 对这个也是刚刚学习阶段 xff0c 所以在这里遇到了一个问题 xff1a error static assertion fail
  • eclipse报错“Symbol could not be resolved”,但是编译没有问题

    Eclipse作为一个强大的编辑器 xff0c 可以用来做很多的工作 xff0c 在Eclipse中偶然遇到一个问题 Symbol could not be resolved xff0c 但是编译能够通过 xff1b 这个问题网上有很多人有
  • LCD屏幕调试过程(驱动IC ST7701s)

    调试准备工作 1 屏幕开发手册 xff1b 2 逻辑分析仪 xff08 用来捕获信号 xff0c 信号是否正确 xff09 xff1b 3 驱动板 xff0c 驱动屏幕显示 xff1b 屏幕接口 根据手册的说明 xff0c 可以知道屏幕的一
  • Ubuntu 18.04 安装Open3D C++版本

    此篇博客引用博客Ubuntu18 04 安装Open3D C 43 43 与Python版本 zpwhust的博客 CSDN博客 ubuntu 安装open3d 并在此基础上进行整理 环境 linux ubuntu 18 04 cmake
  • C++ 编译出现问题 -(undefined reference to `vtable for xxx‘)

    在编码遇到这个问题 xff0c 记录一下 xff0c 代码结构如下 class father father father class son public father son father son 乍一看 xff0c 没啥不对的 xff0
  • 实用工具合集

    工作中遇到的比较好用的网站 xff0c 记录一下 数学 1 3D Rotation converter 这是一个欧拉角 xff0c 旋转矩阵 xff0c 旋转向量相互转换的网站 2 坐标系 实时显示函数的一个网站 xff0c 功能强大 xf
  • Opencv3.2安装opencv_contrib-3.2

    在open3 x的版本中 xff0c 图像特征提取的算法并未在源码中 xff0c 需要从OpenCV contrib 3 2编译安装 xff0c 下面就是记录一下编译安装的过程 下载 opencv contrib 3 2下载地址 编译 cm
  • vector的成员函数解析

    vector是线性容器 它的元素严格的按照线性序列排序 和动态数组很相似 和数组一样 它的元素存储在一块连续的存储空间中 这也意味着我们不仅可以使用迭代器 iterator 访问元素 还可以使用指针的偏移方式访问 和常规数组不一样的是 ve
  • ROS编程遇到的错误小结

    1 终端出现MD5值不匹配问题 这种情况 xff0c 是由于通信双方的数据内容不同 持续更新
  • HTML 和 XML 数据的分析与解析

    引言 目前在 Java 中 xff0c 解析 HTML 工具主要包含以下几种 xff1a jsoup xff1a 强大的 HTML 解析工具 xff0c 支持以 jQuery 中 CSS Selector 的方式提取 HTML 中的元素 x
  • 【掌控板】0、基础教程

    环境搭建 软件 xff1a mind 43 硬件 xff1a 掌控板2 0 mind 43 使用界面 项目 新建项目 连接掌控板和pc 我的显示有问题 xff0c 是因为我原先代码出错了 xff0c 正常情况下会显示掌控板 驱动更新好了在m
  • 方波的产生——运算放大器LM324产生方波

    方波的产生 运算放大器LM324产生方波 双电源供电 xff08 1 xff09 搭建振荡电路如图所示 xff0c 先采用双电源供电讲解 xff0c 需要两个滑动变阻器RP1和RP2 xff0c 一个固定电阻R1和一个电容C1 xff0c
  • Android Studio开发手机APP(一)

    Day1 新建工程 软件安装可以参考Android第一天 安装Android Studio 3 5 一 打开Android Studio xff0c 新建工程 xff08 Android Studio版本 xff1a Version 3 5
  • 在Win10上使用Linux子系统和VSCode搭建C语言开发环境

    在Win10上使用Linux子系统和VSCode搭建C语言开发环境 一 启动Windows下的Linux子系统 打开控制面板 xff0c 点击卸载程序 点击右侧的 启用和关闭Windows功能 找到适用于Linux的Windows子系统 x
  • C语言网络编程(3)— 通过DNS连接到百度

    C语言网络编程 xff08 3 xff09 通过DNS连接到百度 一 gethostbyname 函数 我们现在认知一台计算机主机通常采用直观可读的名字 例如百度我们会记住 www baidu com 而不是他的IP地址 对于大多数的应用程
  • C语言网络编程(4)— 通过DNS连接到百度-优化

    C语言网络编程 xff08 4 xff09 通过DNS连接到百度 优化 一 gethostbyname和getaddrinfo 之前我们使用gethostbyname 函数完成了主机名到地址的解析 xff0c 但这个函数仅仅支持IPv4 x
  • C语言网络编程(5)— MQTT通信

    C语言网络编程 xff08 5 xff09 MQTT通信 一 下载mqtt C语言库 首先我们要下载支持MQTT的C语言库 xff0c 直接使用git命令拉取 xff1a span class token function git span