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()
{
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);
}