微消息队列MQTT(3)(实现一个简单Mqtt客户端)

376 阅读3分钟
相关文档
阿里云(C语言接入 阿里云Mqtt微消息队列相关文档):
https://help.aliyun.com/document_detail/146611.html?spm=a2c4g.11186623.6.1007.5c5725932sKjsl
https://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/index.html?spm=a2c4g.11186623.2.8.72a8379bBBeLUj
CSDN:
https://blog.csdn.net/qq_43260665/article/details/88370100
1:下载一个Paho C库
1:先进入一个文件夹 
    cd /opt/iot
2:使用git命令下载库    
    git clone https://github.com.cnpmjs.org/eclipse/paho.mqtt.c.git
3:进行编译安装:
        1:cd paho.mqtt.c
        //编译
        2:make
        //安装
        3:sudo make install
2:查看动态库
cd build/output
存在以下文件

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

在samples中还会有一些示例代码;
MQTTAsync_publish   MQTTAsync_subscribe
MQTTClient_publish   MQTTClient_subscribe   MQTTClient_publish_async        
paho_c_pub      paho_cs_sub
paho_cs_pub     paho_c_sub 
3:编写 发布端(客户端)代码 mqtt_publish.c

vim

////引用相关库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"

//定义常量
#define ADDRESS     "tcp://post-cn-nif23a2s52f.mqtt.aliyuncs.com:1883"
#define CLIENTID    "ExampleClientPub"
#define TOPIC       "topic_mqtt"
//#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000

//以下为	发布者客户端
int main(int argc, char* argv[])
{
    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
	
	//临时参数
    int rc;
	
	//创建一个发布者 客服端
    MQTTClient_create(&client, ADDRESS, CLIENTID,MQTTCLIENT_PERSISTENCE_NONE, NULL);
	//设置相关的连接参数
    conn_opts.keepAliveInterval = 60;
    conn_opts.cleansession = 1;
	
	//使用客户端连接服务端
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
	
	//设置发送的消息
    
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
	

	char buf[1024];
	while(1){
		printf("enter the message you want to send\n");
		fgets(buf,sizeof(buf),stdin);
		pubmsg.payload = (void *)buf;
		pubmsg.payloadlen = strlen(buf);
		MQTTClient_publishMessage(client,TOPIC,&pubmsg,&token);
		printf("waiting for %d seconds for publication of %s on topic %s for client with CLIENTID :%s\n",TIMEOUT/1000,buf,TOPIC,CLIENTID);
		int rv=MQTTClient_waitForCompletion(client,token,TIMEOUT);
		printf("Message with delivery token %d delivered\n",rv);
		//用于测试
		printf("%s\n",buf);
        sleep(3);
	}
}
    
4:进行编译 运行 mqtt_publish.c
编译:gcc mqtt_publish.c 
-L(大写的L) -I(大写的I)
查找对应的包:-o mqtt_publish -lpaho-mqtt3c -L ./opt/iot/paho.mqtt.c/ -I ./opt/iot/paho.mqtt.c/src/ 
说明 :如果没有将头文件和动态库放到编译器默认寻找的位置 需要在编译时指定包

进行编译:
gcc mqtt_publish.c -o mqtt_publish -lpaho-mqtt3c -L ./opt/iot/paho.mqtt.c/ -I ./opt/iot/paho.mqtt.c/src/

进行运行
./mqtt_publish

返回:   mqtt的客户端还没运行
MQTTClient_connect failure:Transport endpoint is not connected

5:编写 订阅端(客户端)代码 mqtt_subscribe.c
////引用相关库
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"

//定义常量
#define ADDRESS     "tcp://post-cn-nif23a2s52f.mqtt.aliyuncs.com:1883"
#define CLIENTID    "ExampleClientSub"
#define TOPIC       "topic_mqtt"
#define PAYLOAD     "Hello World!"
#define QOS         1
#define TIMEOUT     10000L

volatile MQTTClient_deliveryToken token;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("Message with token value %d delivery confirmed\n", dt);
    token = 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
    {
        q = getchar();
    } while(ch!='Q' && ch != 'q');
	
	//断开客户端连接
    MQTTClient_disconnect(client, 10000);
	//销毁客户端连接
    MQTTClient_destroy(&client);
    return rc;
}

6:进行编译 运行 mqtt_subscribe.c
先打开另一个客户端
然后进入该文件夹 /opt/iot/paho.mqtt.c/build/code

进行编译:
 gcc mqtt_subscribe.c -o mqtt_subscribe -lpaho-mqtt3c -L ./opt/iot/paho.mqtt.c/build/output/
进行运行:
./mqtt_subscribe

报错:
MQTTClient_connect failure:Transport endpoint is not connected

先去阿里云服务器管理  放开1883端口
7:测试
在发布端(客户端)进行消息的发送
在订阅端(客户端) 进行消息的接收
查看相关的打印 并查看阿里云平台的mqtt