Linux PAHO MQTT异步订阅与发布,没有SSL加密

1.下载PAHO MQTT包
wget https://codeload.github.com/eclipse/paho.mqtt.c/tar.gz/refs/tags/v1.3.13
2.解压PAHO MQTT压缩包
tar -zxvf paho.mqtt.c-1.3.13.tar.gz
3.创建生成文件位置
mkdir build
在这里插入图片描述
4.cd build
5.配置交叉编译
cmake -DPAHO_WITH_SSL=TRUE -DOPENSSL_ROOT_DIR=/home/seuls/Documents/libs/openssl-1.1.1w/build -DCMAKE_INSTALL_PREFIX=$PWD/install -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc …
说明:
1.DPAHO_WITH_SSL:是否开启SSL加密,开启为TRUE,不开启为FALSE
2.DOPENSSL_ROOT_DIR:SSL校验的相关路径
3.X-DCMAKE_INSTALL_PREFIX:是指定paho最终的安装路径用的
4.DCMAKE_C_COMPILER:交叉编译工具链的名称
注:如果不需要SSL校验,将DPAHO_WITH_SSL设为FALSE,DCMAKE_INSTALL_PREFIX不设置
6.make编译
7.make install安装
8.安装成功后生成4个文件夹
在这里插入图片描述
1.include中生成的是头文件
在这里插入图片描述
2.lib是生成的动态库
在这里插入图片描述
9.实现PAHO MQTT异步订阅和发布
1.需要将交叉编译生成的include和lib拷贝到项目当中
在这里插入图片描述
注:主要需要的是头文件MQTTAsync.h和静态库lib paho-mqtt3a.so和libpaho-mqtt3c.so
2.代码说明
设置登录MQTT端的账号、密码

`#include "MQTTAsync.h"
#define ADD_TIME_MS	0	//8*3600*1000

char g_sn[64] = "xxxxxx";//客户端标识符
char g_account[] = "xxxx";//用户名
char g_pwd[] = "xxxxx";//密码

char g_clientId[64];
char s_ServerIp[] = "xxx.xxx.xxx.xxx";//mqtt服务器地址

static const char* OPT_SEND = "MQTTAsync_sendMessage";
static const char* OPT_SUB = "MQTTAsync_subscribe";
static const char* OPT_UNSUB = "MQTTAsync_unsubscribe";
static MQTTAsync s_Client = NULL;//通过 MQTTAsync_create() 创建的 MQTT 客户端实例
static int s_cloudStatus = DEVICE_OFFLINE;

extern pthread_mutex_t g_db_mutex;
volatile DEObjectSt g_detectionStatus;
MQTTInfoSt g_mqttObj;

创建mqtt客户端

int MQTTAsync ps_MQTT_Connect(void)
{

int rc = 0;
char temp_address[128] = {0}; //服务器地址
FILE *fp; 	
char topicBuf[256] = {0};
char *message = NULL;
	
	MQTTAsync_createOptions opts  = MQTTAsync_createOptions_initializer;//用于设置创建选项,比如连接超时时间、是否自动重连等
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;//设置连接的选项结构体初始化
	MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;//遗嘱消息结构体初始化
	MQTTAsync_setTraceCallback(mqttTraceCallback);
	opts.MQTTVersion = MQTTVERSION_5;//要使用的 MQTT 版本
	sprintf(topicBuf, "/xxx/%s/xxx");//topic内容
	strncpy(g_mqttObj.ip,s_ServerIp,sizeof(s_ServerIp));
	g_mqttObj.port = xxxx;//端口号
	sprintf(temp_address,"tcp://%s:%d",g_mqttObj.ip, g_mqttObj.port);
	//创建mqtt客户端
	if ((rc = MQTTAsync_createWithOptions(&s_Client, temp_address, g_sn, MQTTCLIENT_PERSISTENCE_NONE, NULL,&opts)) != MQTTASYNC_SUCCESS)
	{
		return NULL;
	}
	
	/*Set the mqtt callback*/
	mqtt_set_callbacks();
	cJSON* willPayload = cJSON_CreateObject();
	if (willPayload){
		conn_opts.keepAliveInterval = 30;//心跳包发送间隔时间
		conn_opts.connectTimeout = CONNECT_TIMEOUT;
		conn_opts.automaticReconnect = AUTO_CONN;//开启断开自动重连
		conn_opts.minRetryInterval = 1;//最小重连间隔时间(秒),每次失败重连间隔时间都会加倍
		conn_opts.maxRetryInterval = 32;//最大重连间隔时间(秒)
		//conn_opts.username = USRNAME;
		//conn_opts.password = PASSWORD;	
		conn_opts.username = g_account;
		conn_opts.password = g_pwd;
		conn_opts.cleansession = 0;//连接标识,为 1 时表示启用“干净会话”
		conn_opts.onSuccess = onConnect;/*连接成功回调,此处设置的回调只在第一次连接成功时调用,SDK内部自动重连时不会调用;*/
		conn_opts.onFailure = onConnectFailure;//连接失败回调
		conn_opts.context = s_Client;
		will_opts.retained = 0;  //retained = 1 时, broker会一直保留消息,这里不需要,使用默认的0就行
		will_opts.topicName = topicBuf;

		message = ps_will_message_create(willPayload);
		
		if (message){
			will_opts.message = message;
		}
		conn_opts.will = &will_opts;
		建立与 MQTT 代理(服务器)连接	一个异步的 MQTT 客户端实现
		if ((rc = MQTTAsync_connect(s_Client, &conn_opts)) != MQTTASYNC_SUCCESS)
		{
		/*	rc的返回值为正确,大于为错误代码
			1:连接被拒绝 - 不可接受的协议版本。
			2:连接被拒绝 - 标识符被拒绝。
			3:连接被拒绝 - 服务器不可用。
			4:连接被拒绝 - 用户名或密码错误。
			5:连接被拒绝 - 未经授权
			*/
			if (message){
				cJSON_free(message);
			}
			if(willPayload)
			{
				cJSON_Delete(willPayload);
			}
			
			return NULL;
		}
		if (message){
			cJSON_free(message);
		}
		if(willPayload)
		{
			cJSON_Delete(willPayload);
		}
	}

	return s_Client;
}

订阅主题

int ps_MQTT_SubTopic(char *topicName)
{
	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	int rc;
	opts.onSuccess = onOptSuccess;
	opts.onFailure = onOptFail;
	opts.context = (void*)OPT_SUB;

	if(s_cloudStatus == DEVICE_OFFLINE){
		return -1;
	}
	if ((rc = MQTTAsync_subscribe(s_Client,topicName, QOS, &opts)) != MQTTASYNC_SUCCESS)
	{
		return -1;
	}
	return 0;
}
**向主题发布消息**
int ps_MQTT_SendMsg(char *topicName,const char *payload)
{
	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
	int rc = 0;
	opts.onSuccess = onOptSuccess;
	opts.onFailure = onOptFail;
	opts.context =  (void*)OPT_SEND;

	pubmsg.payload = (void*)payload;
	pubmsg.payloadlen = strlen(payload);
	pubmsg.qos = QOS;
	pubmsg.retained = 0;

	if(s_cloudStatus == DEVICE_OFFLINE){
		return -1;
	}
	//向MQTT服务器发送消息
	if(s_Client){
		if ((rc = MQTTAsync_sendMessage(s_Client, topicName, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
		{
			return -1;
		}
	}
	
	return rc;

}

解释:topicName:要发布消息的目标主题名称
payload:发布的内容
取消订阅

int ps_MQTT_UnsubTopic(const char *topicName)
{
	debug_log(LOGT_INFO, "to unsubtopic:%s \n",topicName);

	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
	int rc;

	opts.onSuccess = onOptSuccess;
	opts.onFailure = onOptFail;
	opts.context = (void*)OPT_UNSUB;

	if(s_cloudStatus == DEVICE_OFFLINE){
		return -1;
	}
	//取消订阅 MQTT 主题
	if ((rc = MQTTAsync_unsubscribe(s_Client,topicName,&opts)) != MQTTASYNC_SUCCESS)
	{
		return -1;
	}
	return rc;
}

回调函数

static void mqtt_set_callbacks(void)
{
	MQTTAsync_setConnectionLostCallback(s_Client,NULL,connlost);// MQTT 客户端与 MQTT 服务器的连接丢失时调用的回调函数
	MQTTAsync_setMessageArrivedCallback(s_Client,NULL,messageArrived);//设置当 MQTT 客户端接收到新消息时调用的回调函数
	MQTTAsync_setDeliveryCompleteCallback(s_Client,NULL,onDeliveryComplete);//用于设置当 MQTT 客户端发送的消息被成功接收到时调用的回调函数
	MQTTAsync_setConnected(s_Client,NULL,onConnectBuild);//用于设置当 MQTT 客户端成功连接到 MQTT 服务器时调用的回调函数
	//此函数尝试断开客户端与MQTT的连接服务器。以便让客户端有时间完成消息处理当调用此函数时,超时时间为指定。当超时时间超过时,客户端甚至断开连接如果仍有未完成的邮件确认
	MQTTAsync_setDisconnected(s_Client,NULL,onDisConnected);//用于设置当 MQTT 客户端与 MQTT 服务器断开连接时调用的回调函数
	//MQTTAsync_setCallbacks
}

接收订阅主题消息函数

int messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message)
{
	MQTTAsync_freeMessage(&message);
	MQTTAsync_free(topicName);
	return 1;
}

解释:message为接收到的消息
获取运行状态

int ps_get_cloud_status(void)
{
	return s_cloudStatus;
}

连接丢失

static void connlost(void *context, char *cause)
{
	if(context == NULL || cause == NULL)
	{
		s_cloudStatus = DEVICE_OFFLINE;
		return;
	}
	char topicBuf[256] = {0};
	char *message = NULL;	
	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
	MQTTAsync_willOptions will_opts = MQTTAsync_willOptions_initializer;
	int rc;
	char ccuid[32] = {0};
	char pid[32] = {0};
	sprintf(topicBuf, "/inspection/%s/heartbeat", g_sn);
	debug_log(LOGT_INFO, "\nConnection lost\n");
	debug_log(LOGT_INFO, "cause: %s\n", cause);
	s_cloudStatus = DEVICE_OFFLINE;

	cJSON* willPayload = cJSON_CreateObject();
	if (willPayload){
		message = ps_will_message_create(willPayload);
		if (message){
			conn_opts.keepAliveInterval = 20;
			conn_opts.cleansession = 0;
			will_opts.retained = 0;  //retained = 1 时, broker会一直保留消息,这里不需要,使用默认的0就行
			will_opts.topicName = topicBuf;
			will_opts.message = message;
			conn_opts.will = &will_opts;	
			if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
			{
				debug_log(LOGT_ERR, "Failed to start connect, return code %d\n", rc);
			}
			cJSON_free(message);
		}
		message = NULL;
		cJSON_Delete(willPayload);	
	}
	willPayload = NULL;
}

断开连接失败

void onDisconnectFailure(void* context, MQTTAsync_failureData* response)
{
}

断开连接
void onDisconnect(void* context, MQTTAsync_successData* response)
{

}
发送消息失败

void onSendFailure(void* context, MQTTAsync_failureData* response)
{
	if(context == NULL || response == NULL)
	{
		return;
	}

	MQTTAsync client = (MQTTAsync)context;
	MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
	int rc;
	opts.onSuccess = onDisconnect;
	opts.onFailure = onDisconnectFailure;
	opts.context = client;
	//断开MQTT客户端与MQTT服务器连接
	if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
	{
	}
}

发送消息

void onSend(void* context, MQTTAsync_successData* response)
{
	if(response == NULL)
	{
		return;
	}
}

连接失败

void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
	if(response == NULL)
	{
		return;
	}
}

补充

static void onOptSuccess(void* context, MQTTAsync_successData* response)
{
	if(strcmp((char *)context,OPT_SEND)==0)
	{
	}
	else if(strcmp((char *)context,OPT_SUB)==0)
	{
	}
	else if(strcmp((char *)context,OPT_UNSUB)==0)
	{
	}
}
static void onOptFail(void* context,  MQTTAsync_failureData* response)
{
	if(strcmp((char *)context,OPT_SEND)==0)
	{
	}
	else if(strcmp((char *)context,OPT_SUB)==0)
	{
	}
	else if(strcmp((char *)context,OPT_UNSUB)==0)
	{
	}
}

10.相关资料
https://github.com/eclipse/paho.mqtt.c

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值