VC MFC C++ MQTT VC编译MQTT VC调用MQTT dll eclipse-paho-mqtt

↘锁芯ラ 提交于 2020-09-30 02:53:37

VC MFC C++ MQTT VC编译MQTT VC调用MQTT dll eclipse-paho-mqtt

JS HTML Web端使用MQTT通讯测试

 

系统:Windows10 64位

开发环境:Visual Studio 2013 64位

MQTT源码库:eclipse-paho-mqtt-c-src-1.2.0

测试工具:MQTTBox

MQTT服务器:阿里云部署EMQX

VC MFC程序运行图示:

一、编译MQTT 生成dll lib

1、下载MQTT源码库:eclipse-paho-mqtt-c-src

      下载github地址:https://github.com/eclipse

2、解压、使用Visual Studio编译出动态链接库

      解压eclipse-paho-mqtt-c-src

3、使用Visual Studio编译dll/lib

打开目录eclipse-paho-mqtt-c-src-1.2.0\Windows Build中的Paho C MQTT APIs.sln工程

使用VS菜单->生成->生成解决方案,来生成dll和lib,生成目录为eclipse-paho-mqtt-c-src-1.2.0\Windows Build\Debug

错误和失败的是带SSL的,需要电脑安装OPENSSL库才能编译,需要SSL需求的同学自己安装OPENSSL再编译

paho-mqtt3a : 一般实际开发中就是使用这个,a表示的是异步消息推送(asynchronous)。

paho-mqtt3as : as表示的是 异步+加密(asynchronous+OpenSSL)。

paho-mqtt3c : c 表示的应该是同步(Synchronize),一般性能较差,是发送+等待模式。

paho-mqtt3cs : 同上,增加了一个OpenSSL而已

带S的都需要OpenSSL才能编译,test工程也一样

我的电脑没安装OpenSSL,所以只生成了

paho-mqtt3a.dll 

paho-mqtt3a.lib

paho-mqtt3c.dll

paho-mqtt3c.lib

一般使用足够了,保存关闭工程,以后编译还会用到。

二、调用dll lib编写VC MQTT客户端

1、新建MFC工程

选择MFC用户程序,向导中选择基于对话框,在共享dll中使用MFC

2、设置链接和头文件

将eclipse-paho-mqtt-c-src-1.2.0\src目录中所有文件复制到此工程目录中include目录中(新建)

在工程中创建一个MQTT筛选器,添加MQTTAsync.h和MQTTClient.h

将刚才生成的dll复制到工程目录Debug,将刚才生成的lib复制到工程目录工程源码目录中

在工程属性页添加lib链接库

3、设计界面

4、编写代码,以下只列出MQTT调用核心代码,界面控件的响应和控制就不列出了,只实现基础功能,后期再添加新功能

包含头文件

连接服务器代码

	MQTT_Conn_opts = MQTTClient_connectOptions_initializer;
	MQTT_Pubmsg = MQTTClient_message_initializer;
	
	int rc;
	MQTTClient_create(&MQTT_Client, ServerAddStr, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
	MQTT_Conn_opts.keepAliveInterval = atoi(KeepAliveStr);
	MQTT_Conn_opts.cleansession = 1;
	MQTT_Conn_opts.username = UserName;
	MQTT_Conn_opts.password = PassWord;

	MQTTClient_setCallbacks(MQTT_Client, NULL, MQTT_ConnLost, MQTT_MsgArrvd, MQTT_Delivered);

	if ((rc = MQTTClient_connect(MQTT_Client, &MQTT_Conn_opts)) != MQTTCLIENT_SUCCESS){
		AfxMessageBox("Failed to connect");// , return code %d\n", rc);
		return;
	}
	else{
		printf("MQTT Server Connect OK  \n");
		((CButton*)GetDlgItem(IDC_BUTTON_ConnectServer))->SetWindowText("断开连接");//填入文本框
		GetDlgItem(IDC_BUTTON_SendMsg)->EnableWindow(TRUE);// 发布按钮有效
	}

断开连接代码

// 断开连接
void CMQTT_TestDlg::DisconnectConnect()
{
	MQTTClient_disconnect(MQTT_Client, 10000);
	MQTTClient_destroy(&MQTT_Client);
	((CButton*)GetDlgItem(IDC_BUTTON_ConnectServer))->SetWindowText("连接服务器");//填入文本框
}

发送消息代码

// 发布消息按钮
void CMQTT_TestDlg::OnBnClickedButtonSendmsg()
{
	int rc;
	CString PublishStr, SendMsgStr;
	((CEdit*)GetDlgItem(IDC_EDIT_Publish))->GetWindowText(PublishStr);//获取文本框内容
	((CEdit*)GetDlgItem(IDC_EDIT_SendMsg))->GetWindowText(SendMsgStr);//获取文本框内容
	char buff[2048];
	memset(buff, 0, sizeof(buff));
	strcpy_s(buff, sizeof(buff),SendMsgStr );
	MQTT_Pubmsg.payload = buff;
	MQTT_Pubmsg.payloadlen = strlen(buff);
	MQTT_Pubmsg.qos = QOS;
	MQTT_Pubmsg.retained = 0;
	MQTTClient_publishMessage(MQTT_Client, PublishStr, &MQTT_Pubmsg, &MQTT_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), SendMsgStr, PublishStr, CLIENTID);
	rc = MQTTClient_waitForCompletion(MQTT_Client, MQTT_Token, TIMEOUT);
	printf("Message with delivery token %d delivered\n", MQTT_Token);
	while (deliveredtoken != MQTT_Token);
}

订阅按钮代码

// 订阅按钮
void CMQTT_TestDlg::OnBnClickedButtonSubscribe()
{
	/* 订阅多条
	char *const topics[] = { (char*)"topics1","topics2" };
	//rc = MQTTClient_unsubscribeMany(client, 2, topics);
	*/
	CString SubscribeStr;
	((CEdit*)GetDlgItem(IDC_EDIT_SubscribeMsg))->GetWindowText(SubscribeStr);//获取文本框内容
	if (SubscribeStr.GetLength() <= 0){
		AfxMessageBox("请输入要订阅的消息");
	}else{
		if (MQTTClient_subscribe(MQTT_Client, SubscribeStr, QOS) == MQTTCLIENT_SUCCESS){
			int n = m_SubscribeList.GetItemCount();//获取list里面有多少行
			m_SubscribeList.InsertItem(n, SubscribeStr);//插入行
			((CEdit*)GetDlgItem(IDC_EDIT_SubscribeMsg))->SetWindowText("");//填入文本框
		}else{
			AfxMessageBox("订阅失败");
		}
	}
}

取消订阅代码

// 取消订阅按钮
void CMQTT_TestDlg::OnBnClickedButtonUnsubscribe()
{
	//获取选中的行
	int r = m_SubscribeList.GetSelectionMark();
	if (m_SubscribeList.GetSelectedCount() != 0){
		CString str = m_SubscribeList.GetItemText(r, 0);
		
		printf("取消订阅  第 %d 行  内容:%s\r\n", r,str);
		if (MQTTClient_unsubscribe(MQTT_Client, str) == MQTTCLIENT_SUCCESS){
			m_SubscribeList.DeleteItem(r);
		}else{
			AfxMessageBox("取消订阅失败");
		}
	}else{
		AfxMessageBox("请在列表中选择要取消订阅的消息");
	}
}

消息已送达回调

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

消息到达回调

int MQTT_MsgArrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
	CString RevMsg,LastRevMsg,TopicName,Msg;
	int i;
	char* payloadptr;
	char buf[4096];
	memset(buf, 0, sizeof(buf));
	printf("Message arrived\n");
	printf("     topic: %s\n", topicName);
	printf("   message: ");
	payloadptr = (char *)message->payload;
	for (i = 0; i<message->payloadlen; i++){
		buf[i] = *payloadptr++;
		//putchar(*payloadptr++);
	}
	putchar('\n');
	//memcpy(buf, payloadptr, message->payloadlen);
	TopicName.Format("%s", topicName);
	Msg.Format("%s", buf);
	RevMsg = "\r\n收到 " + TopicName + " 的消息:" + Msg;
	printf("dddddddddddd  %s\r\n", RevMsg);
	CMQTT_TestDlg *pDlg = (CMQTT_TestDlg*)g_pDlg;
	pDlg->AddMsgToMsgBox(RevMsg);

	MQTTClient_freeMessage(&message);
	MQTTClient_free(topicName);
	return 1;
}

服务器连接断开回调

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!