MQTT实例代码解析

注释和头文件

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

#define ADDRESS     "tcp://localhost:1883" 
#define CLIENTID    "ExampleClientPub"    
#define TOPIC       "MQTT Examples"
#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000L

ADDRESS:MQTT代理服务器的地址

CLIENTID:MQTT客户端的唯一标识符

TOPIC:要接收消息的主题名称

PAYLOAD:要发布的消息内容

QOS:消息的服务质量等级。在这个例子中,服务质量等级是1,表示至少一次传递

TIMEOUT:操作的超时时间,以毫秒为单位。在这个例子中,超时时间是10000毫秒,即10秒

定义了结构体的变量

volatile MQTTClient_deliveryToken deliveredtoken;

子函数解析

/*
 *@void *context:上下文信息,可以在回调函数中传递额外的数据或状态。在这个例子中,没有使用上下文信息,所以可以将其忽略。
 *@MQTTClient_deliveryToken dt:消息的传递令牌。
 */
void delivered(void *context,MQTTClient_deliveryToken dt)
{
    printf("Message with token %d delivery xonfirmed\n",dt);//首先打印出消息的传递令牌,以确认消息已经成功传递。
    deliveredtoken = dt;//然后,将传递令牌保存在全局变量deliveredtoken中,以便在其他地方使用。
}

context:上下文信息,可以在回调函数中传递额外的数据或状态。在这个例子中,没有使用上下文信息,所以可以将其忽略

dt:消息的传递令牌

int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char* payloadptr;

    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");

    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

topicName:收到来自哪个主题的消息

topicLen:主题的长度

message:消息体:payload(消息体,字符串)  payloadlen:消息的长度

通过定义回调函数并在其中处理接收到的消息,可以根据需要对消息进行处理,例如打印、存储或执行其他操作。

void connlost(void *context,char *cause)
{
    printf("\nConnection lost\n");//当断开链接时,打印以下内容
    printf("     cause: %s\n",cause);
}

context:指向上下文的指针,可以在函数中使用该指针来访问其他变量或数据

cause:表示连接丢失的原因的字符串

这个函数的目的是在MQTT连接丢失时提供一个通知,以便应用程序可以采取适当的措施,例如重新连接或记录错误信息

主函数解析

int main(int argc, char* argv[])
{
    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;
    int ch;

MQTTClient Client; 定义客户端句柄

MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; 赋值宏定义,可以设置连接选项的各种参数,例如用户名、密码、超时时间等

//创建客户端,并且指定客户端连接的MQTT服务器地址和客户端ID
    MQTTClient_create(&Client,ADDRESS,CLIENTID,MQTTCLIENT_PERSISTENCE_NONE,NULL);
    /*
     *@&Client:指向MQTT客户端实例的指针,用于接收
     *@ADDRESS:MQTT代理服务器的地址。
     *@CLIENTID:客户端的唯一标识符。
     *@MQTTCLIENT_PERSISTENCE_NONE:表示不使用持久化存储。
     *@NULL:表示不使用上下文信息。
     */

Client:指向MQTT客户端实例的指针,用于接收

ADDRESS:MQTT代理服务器的地址

CLIENTID:客户端的唯一标识符

MQTTCLIENT_PERSISTENCE_NONE:表示不使用持久化存储

NULL:表示不使用上下文信息

//初始化链接函数
    conn_opts.keepAliveInterval = 20;//心跳保持间隔为20秒,每隔20秒发一次消息
    conn_opts.cleansession = 1;//清理会话标志设制为1,清除之前的会话信息

conn_opts.keepAliveInterval = 20; 心跳保持间隔为20秒,每隔20秒发一次消息

conn_opts.cleansession = 1; 清理会话标志设制为1,清除之前的会话信息

//设置回调接口,只需要关注msgarrvd:消息到达后,会自动调用这个接口
    MQTTClient_setCallbacks(Client,NULL,connlost,msgarrvd,delivered);
    /*
     *@Client:MQTT客户端实例。
     *@NULL:表示不使用上下文信息。
     *@connlost:连接丢失回调函数,用于在连接断开时执行相应的操作。
     *@msgarrvd:消息到达回调函数,用于在接收到订阅的消息时执行相应的操作。
     *@delivered:消息传递完成回调函数,用于在消息成功传递到代理服务器时执行相应的操作。
     */

Client:MQTT客户端实例

NULL:表示不使用上下文信息

connlost:连接丢失回调函数,用于在连接断开时执行相应的操作

msgarrvd:消息到达回调函数,用于在接收到订阅的消息时执行相应的操作

delivered:消息传递完成回调函数,用于在消息成功传递到代理服务器时执行相应的操作

//链接到broker
    if((rc = MQTTClient_connect(Client,&conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

     printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);

    //订阅某个主题,指定订阅主题的名字,可以指定qos服务质量
    MQTTClient_subscribe(Client, TOPIC, QOS);  

代码尝试使用MQTTClient_connect函数连接到broker,并将连接选项conn_opts作为参数传递。如果连接成功,则返回值rc将为MQTTCLIENT_SUCCESS,否则将打印连接失败的消息并退出程序,代码使用printf函数打印出订阅的主题、客户端ID和服务质量等信息,最后,使用MQTTClient_subscribe函数订阅指定的主题。它接受三个参数:Client表示MQTT客户端对象,TOPIC表示要订阅的主题名称,QOS表示订阅的服务质量等级,这段代码的目的是建立与MQTT broker的连接,并订阅一个特定的主题,以接收该主题的消息。

do 
    {
        ch = getchar();
    } while(ch!='Q' && ch != 'q');

待用户输入,直到用户输入字符'Q'或'q'为止

MQTTClient_unsubscribe(client, TOPIC);
    MQTTClient_disconnect(client, 10000);
    MQTTClient_destroy(&client);
    return rc;
}

取消订阅、断开连接和销毁MQTT客户端实例

完整代码展示

/*******************************************************************************
 * Copyright (c) 2012, 2017 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution. 
 *
 * The Eclipse Public License is available at 
 *   http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Ian Craggs - initial contribution
 *******************************************************************************/

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

#define ADDRESS     "tcp://localhost:1883"
#define CLIENTID    "ExampleClientSub"
#define TOPIC       "MQTT Examples"
#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000L

volatile MQTTClient_deliveryToken deliveredtoken;

void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char* payloadptr;

    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");

    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}

int main(int argc, char* argv[])
{
    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;
    int ch;

    MQTTClient_create(&client, ADDRESS, CLIENTID,
        MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;

    MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);

    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
    MQTTClient_subscribe(client, TOPIC, QOS);

    do 
    {
        ch = getchar();
    } while(ch!='Q' && ch != 'q');

    MQTTClient_unsubscribe(client, TOPIC);
    MQTTClient_disconnect(client, 10000);
    MQTTClient_destroy(&client);
    return rc;
}

使用实例(订阅和发布)

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

#define ADDRESS "tcp://192.168.158.129:1883"    //MQTT代理服务器的地址
#define CLIENTID "yyyyyyyy" //MQTT客户端的唯一标识符
#define TOPIC "down"  //要接收消息的主题名称
#define TOPIC2 "up" //要发布消息的主题名称
#define PAYLOAD "Hello World!"  //要发布的消息内容。
#define QOS 1   //消息的服务质量等级。在这个例子中,服务质量等级是1,表示至少一次传递。
#define TIMEOUT 10000L  //操作的超时时间,以毫秒为单位。在这个例子中,超时时间是10000毫秒,即10秒。

//定义了结构体的变量
volatile MQTTClient_deliveryToken deliveredtoken;

/*
 *@void *context:上下文信息,可以在回调函数中传递额外的数据或状态。在这个例子中,没有使用上下文信息,所以可以将其忽略。
 *@MQTTClient_deliveryToken dt:消息的传递令牌。
 */
void delivered(void *context,MQTTClient_deliveryToken dt)
{
    printf("Message with token %d delivery xonfirmed\n",dt);//首先打印出消息的传递令牌,以确认消息已经成功传递。
    deliveredtoken = dt;//然后,将传递令牌保存在全局变量deliveredtoken中,以便在其他地方使用。
}
/**
 * @brief 
 * 
 * @param context 
 * @param topicName 收到来自哪个主题的消息
 * @param topicLen 主题的长度
 * @param message 消息体:payload(消息体,字符串)  payloadlen:消息的长度
 * @return int 
 */
int msgarrvd(void *context,char *topicName,int topicLen,MQTTClient_message *message)
{
    int i;
    char *payloadptr;
    cJSON *root = cJSON_Parse((char *)message->payload);
    if(NULL == root)
    {
        printf("Message arrivd\n");//在回调函数中,首先打印出收到消息的主题名称和消息内容。
        printf("     topic 传输的JSON格式有误\n");//printf函数用于打印字符串和变量的值。%s是格式化字符串的占位符,用于打印字符串类型的值。
        printf("   message: ");
    }
    else
    {
        printf("Message arrivd\n");//在回调函数中,首先打印出收到消息的主题名称和消息内容。
        printf("     topic %s\n",topicName);//printf函数用于打印字符串和变量的值。%s是格式化字符串的占位符,用于打印字符串类型的值。
        printf("   message: ");
    
#if 0
    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
#endif
        printf("recv msg = %s\n", (char *)message->payload);//(char *)message->payload是将消息内容转换为字符串类型。

        MQTTClient_freeMessage(&message);//然后,使用MQTTClient_freeMessage函数释放接收到的消息的内存。
        /*message是一个指向MQTTClient_message结构体的指针,用于指定要释放的消息。 */
        MQTTClient_free(topicName);//接下来,使用MQTTClient_free函数释放接收到消息的主题名称的内存。
        /*topicName是一个指向字符数组的指针,用于指定要释放的主题名称。 */
    }
    return 1;//最后,返回值为1,表示消息已经处理完毕。
}
/*通过定义回调函数并在其中处理接收到的消息,可以根据需要对消息进行处理,例如打印、存储或执行其他操作。 */

void connlost(void *context,char *cause)
{
    printf("\nConnection lost\n");//当断开链接时,打印以下内容
    printf("     cause: %s\n",cause);
}

int main(int argc, char const *argv[])
{
    //客户端句柄
    MQTTClient Client;//定义结构体变量
    //链接参数
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;//赋值宏定义
    /*可以设置连接选项的各种参数,例如用户名、密码、超时时间等。 */

    MQTTClient_message pubmsg = MQTTClient_message_initializer;//将pubmsg的所有字段初始化为默认值。
    MQTTClient_deliveryToken token;//接收消息的传递令牌

    int rc;
    int ch;

    //创建客户端,并且指定客户端连接的MQTT服务器地址和客户端ID
    MQTTClient_create(&Client,ADDRESS,CLIENTID,MQTTCLIENT_PERSISTENCE_NONE,NULL);
    /*
     *@&Client:指向MQTT客户端实例的指针,用于接收
     *@ADDRESS:MQTT代理服务器的地址。
     *@CLIENTID:客户端的唯一标识符。
     *@MQTTCLIENT_PERSISTENCE_NONE:表示不使用持久化存储。
     *@NULL:表示不使用上下文信息。
     */

    //初始化链接函数
    conn_opts.keepAliveInterval = 20;//心跳保持间隔为20秒,每隔20秒发一次消息
    conn_opts.cleansession = 1;//清理会话标志设制为1,清除之前的会话信息

    //设置回调接口,只需要关注msgarrvd:消息到达后,会自动调用这个接口
    MQTTClient_setCallbacks(Client,NULL,connlost,msgarrvd,delivered);
    /*
     *@Client:MQTT客户端实例。
     *@NULL:表示不使用上下文信息。
     *@connlost:连接丢失回调函数,用于在连接断开时执行相应的操作。
     *@msgarrvd:消息到达回调函数,用于在接收到订阅的消息时执行相应的操作。
     *@delivered:消息传递完成回调函数,用于在消息成功传递到代理服务器时执行相应的操作。
     */

    //链接到broker
    if((rc = MQTTClient_connect(Client,&conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

     printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);

    //订阅某个主题,指定订阅主题的名字,可以指定qos服务质量
    MQTTClient_subscribe(Client, TOPIC, QOS);  

     //死循环,直到收到了一个q就退出
    char buf[1024]="";
    char buf1[1024]="";
    do 
    {
        bzero(buf,sizeof(buf));//清空数组
        bzero(buf1,sizeof(buf1));//清空数组
        cJSON *root = cJSON_CreateObject();//创建一个树干
        //创建名叫name的子树杈
        cJSON *item = cJSON_CreateString("yyyyyyyy");
        //把子树杈放到树干上
        cJSON_AddItemToObject(root, "name", item);
        //创建名叫age的子树杈
        item = cJSON_CreateNumber(14);
        //把子树杈放到树干上
        cJSON_AddItemToObject(root, "age", item);
        //创建名叫name的子树杈
        fscanf(stdin,"%s",buf1);
        item = cJSON_CreateString(buf1);
        //把子树杈放到树干上
        cJSON_AddItemToObject(root, "msg", item);
        sprintf(buf,"%s",cJSON_PrintUnformatted(root));

        pubmsg.payload = buf;//要发送的内容
        pubmsg.payloadlen = sizeof(buf);//要发送的大小
        pubmsg.qos = QOS;   //服务质量等级是1,表示至少一次传递。
        pubmsg.retained = 0; //要发布的消息是否保留。在这个例子中,保留标志是0,表示不保留消息。
        MQTTClient_publishMessage(Client, TOPIC2, &pubmsg, &token);
        printf("Waiting for up to %d seconds for publication of %s\n"
                "on topic %s for client with ClientID: %s\n",
                (int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID);
        rc = MQTTClient_waitForCompletion(Client, token, TIMEOUT);
        /*
         *@MQTTClient client:MQTT客户端实例。
         *@MQTTClient_deliveryToken token:消息的传递令牌。
         *@unsigned long timeout:等待的超时时间,以毫秒为单位。
         */
        printf("Message with delivery token %d delivered\n", token);//成功发送后打印令牌
    } while(buf[35]!='Q' && buf[36] !='\"');//当数组是大写Q并且第二位没有数时结束

    //取消订阅、断开连接和销毁MQTT客户端实例
    MQTTClient_unsubscribe(Client, TOPIC);
    MQTTClient_unsubscribe(Client, TOPIC2);
    MQTTClient_disconnect(Client, 10000);
    MQTTClient_destroy(&Client);
    return rc;
}

以上代码实现订阅和发送两种功能,用到cJSON.h,编译需要链接paho-mqtt3c

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值