最近做了个中移物联平台的项目,设备需要用到MQTTS来完成通讯,所以使用到了paho-mqtt-c的开源的MQTT协议栈库。
https://www.eclipse.org/paho/index.php?page=downloads.php
非常全,各种语言的源码都有,根据自己需求下载,我这里需要的是C/C++的协议栈。
由于我只需要做一个客户端,做的又是嵌入式设备,源码太多也没用,就精简了一下。
实际上只用了几个重要的
MQTTClient.h
MQTTConnect.h
MQTTFormat.h
MQTTPacket.h
MQTTPublish.h
MQTTSubscribe.h
MQTTUnsubscribe.h
StackTrace.h
以及对应的几个源文件。
实际上所有的头文件都是为了提供给MQTTClient.h使用的。
使用流程
1.创建一个客户端对象;
2.设置连接MQTT服务器的选项;
3.如果多线程(异步模式)操作被使用则设置回调函数(详见 Asynchronous >vs synchronous client applications);
4.订阅客户端需要接收的任意话题;
5.重复以下操作直到结束:
a.发布客户端需要的任意信息;
b.处理所有接收到的信息;
6.断开客户端连接;
7.释放客户端使用的所有内存。
重要的结构,首先要把这个结构体配置了。
typedef struct MQTTClient
{
unsigned int next_packetid,
command_timeout_ms;
size_t buf_size,
readbuf_size;
unsigned char *buf,
*readbuf;
unsigned int keepAliveInterval;
char ping_outstanding;
int isconnected;
int cleansession;
struct MessageHandlers
{
const char* topicFilter;
void (*fp) (MessageData*);
} messageHandlers[MAX_MESSAGE_HANDLERS]; /* Message handlers are indexed by subscription topic */
void (*defaultMessageHandler) (MessageData*);
Network* ipstack;
Timer last_sent, last_received;
#if defined(MQTT_TASK)
Mutex mutex;
Thread thread;
#endif
} MQTTClient;
下面是使用的示例
/*******************************************************************************
* 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"
#if !defined(WIN32)
#include <unistd.h>
#else
#include <windows.h>
#endif
#define ADDRESS "tcp://localhost:1883" //更改此处地址
#define CLIENTID "aaabbbccc" //更改此处客户端ID
#define TOPIC "topic01" //更改发送的话题
#define PAYLOAD "Hello Man, Can you see me ?!" //更改信息内容
#define QOS 1
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
//声明一个MQTTClient
MQTTClient client;
char *username= "test_user"; //添加的用户名
char *password = "aaa777"; //添加的密码
//初始化MQTT Client选项
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
//#define MQTTClient_message_initializer { {'M', 'Q', 'T', 'M'}, 0, 0, NULL, 0, 0, 0, 0 }
MQTTClient_message pubmsg = MQTTClient_message_initializer;
//声明消息token
MQTTClient_deliveryToken token;
int rc;
//使用参数创建一个client,并将其赋值给之前声明的client
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = username; //将用户名写入连接选项中
conn_opts.password = password;//将密码写入连接选项中
//使用MQTTClient_connect将client连接到服务器,使用指定的连接选项。成功则返回MQTTCLIENT_SUCCESS
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &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);
printf("Message with delivery token %d delivered\n", token);
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}