需求:要实现MQTT客户端通信,最终需要变成 MFC 的dll 供别人调用
困难:c++的MQTT库的编译遇到很多障碍,而且有一个现成的c# 写的MQTT通信例子,而且已经验证过可以通信
解决办法:使用 c# 完成MQTT通信,再用c++调用
准备调试环境,准备MQTT服务器,准备MQTT客户端,MQTT服务端我使用 Apollo服务器,客户端使用MQTTX 客户端工具
支持这个服务器运行需要 jdk 环境,版本是jdk 8 点多
https://pan.baidu.com/s/1O4ph-ttUr_KaQzBcERoUVg 提取码:oofx
jdk 安装后需要配置环境变量
系统变量中
Path 中 增加 C:Program Files (x86)Javajdk1.8.0_291in C:Program Files (x86)Javajre1.8.0_291in
增加 JAVA_HOME C:Program Files (x86)Javajdk1.8.0_291
Apollo服务器下载 参考:https://blog.csdn.net/lilealyh/article/details/79867919
https://pan.baidu.com/s/1bMg5XzJaEP5e75lFdAGNEw 提取码:qfhd
创建自己的服务器
下载之后解压到自己电脑的某个目录(d:server)
win+R 进入到命令行进入到一下目录
cd d:serverapolloapache-apollo-1.7.1in
执行命令:
apollo.cmd create myBroker
执行完之后就可以在该目录d:server\apolloapache-apollo-1.7.1in生成一个自己的myBroker文件
启动服务器
每次测试都要启动服务器,别服务器没启动就判断客户端一直连不上
登陆到服务器后台
MQTT客户端 MQTTX
https://pan.baidu.com/s/1h2lpTQeWDpMeRtTVvz_VCQ 提取码:det0 使用方法自己摸索
C# dll 编写
MQTT dll 这个东西是网上下载的 这个环境是.net framework 4.6.1
https://pan.baidu.com/s/13cvuQO_KcvObaYzfnoBLog 提取码: tcyb
创建一个 c# 类库 项目
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; namespace MQTTLibrary { public class MyMQTTClient { private MqttClient m_MQTTClient; //连接 public bool Connect(string sIP, int iPort, string sID, string sUser, string sPSD) { try { m_MQTTClient = new MqttClient(sIP, iPort, false, null, null, 0); m_MQTTClient.MqttMsgPublishReceived += MqttMsgPublishReceived; m_MQTTClient.MqttMsgSubscribed += MqttMsgSubscribedEventHandler; m_MQTTClient.Connect(sID, sUser, sPSD); } catch (Exception ea) { MessageBox.Show("连接失败:" + ea.Message); return false; } return true; } //断开 public bool Disconnect() { if (m_MQTTClient != null && m_MQTTClient.IsConnected) m_MQTTClient.Disconnect(); return true; } public string m_strTop; public string m_strMsg; public delegate void CallBack(string strTopic, string strMsg); //声明委托 public CallBack myCallBack; //发布接收 public void MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e) { m_strTop = e.Topic; m_strMsg = Encoding.UTF8.GetString(e.Message); myCallBack(m_strTop, m_strMsg); //MessageBox.Show(m_strTop); //MessageBox.Show(m_strMsg); } //订阅处理 public void MqttMsgSubscribedEventHandler(object sender, MqttMsgSubscribedEventArgs e) { string top = e.MessageId.ToString(); string val = e.MessageId.ToString(); } //订阅 public bool Subscribe(string strTopic) { string[] STopics = {"1234567890#####", strTopic};//这里是个bug,这个数组只有一个元素的时候会崩溃 byte[] qosLevels = { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE }; try { int val = m_MQTTClient.Subscribe(STopics, qosLevels); } catch (Exception ea) { MessageBox.Show("订阅失败:" + ea.Message); return false; } return true; } //发布 public bool Publish(string strTopic, string strMsg) { try { int val = m_MQTTClient.Publish(strTopic, Encoding.UTF8.GetBytes(strMsg), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false); } catch (Exception ea) { MessageBox.Show("发布失败:" + ea.Message); return false; } return true; } } }
解决方案资源管理器 --> 引用里增加
M2Mqtt.Net xxxxpackagesM2Mqtt.4.3.0.0lib et45M2Mqtt.Net.dll //这是上面下载的mqtt dll 库
MQTTnet xxxxpackagesMQTTnet.3.0.16lib et461MQTTnet.dll //这是上面下载的mqtt dll 库
System.Deployment C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.6.1System.Deployment.dll
System.Drawing C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.6.1System.Drawing.dll
System.Windows.Forms C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.6.1System.Windows.Forms.dll
创建一个MFC对话框程序测试
设置 公共语言运行时支持(/clr)
#using "../debug/xxx.dll"//这里是上面编译出来的dll
using namespace MQTTLibrary;
#include<string>
using namespace std;
#include <vcclr.h>
gcroot<MQTTLibrary::MyMQTTClient^> myMqtt; //声明成全局的变量需要 vcclr.h
1 void CallBack(System::String ^sTopic, System::String ^sMsg) 2 { 3 CString strTopic, strMsg; 4 strTopic = sTopic; 5 strMsg = sMsg; 6 AfxMessageBox(strTopic); 7 AfxMessageBox(strMsg); 8 } 9 10 //连接 11 void CtestMqttDlg::OnBnClickedButton1() 12 { 13 // TODO: 在此添加控件通知处理程序代码 14 myMqtt = gcnew MyMQTTClient(); 15 16 17 myMqtt->myCallBack = gcnew MyMQTTClient::CallBack(&CallBack); 18 19 CString strIP = _T("127.0.0.1"); 20 int iPort = 61613; 21 CString strID; 22 srand((unsigned int)time(NULL)); 23 int num = rand(); 24 strID.Format(_T("mqtt%04d"), num); 25 CString strUser = _T("admin"); 26 CString strPWD = _T("password"); 27 28 System::String ^sIP = gcnew System::String(strIP); 29 System::String ^sID = gcnew System::String(strID); 30 System::String ^sUser = gcnew System::String(strUser); 31 System::String ^sPWD = gcnew System::String(strPWD); 32 33 myMqtt->Connect(sIP, iPort, sID, sUser, sPWD); 34 } 35 36 //断开 37 void CtestMqttDlg::OnBnClickedButton2() 38 { 39 // TODO: 在此添加控件通知处理程序代码 40 41 myMqtt->Disconnect(); 42 } 43 44 //订阅 45 void CtestMqttDlg::OnBnClickedButton3() 46 { 47 // TODO: 在此添加控件通知处理程序代码 48 CString strTopic = _T("123"); 49 System::String ^sTopic = gcnew System::String(strTopic); 50 myMqtt->Subscribe(sTopic); 51 } 52 53 //发布 54 void CtestMqttDlg::OnBnClickedButton4() 55 { 56 // TODO: 在此添加控件通知处理程序代码 57 58 CString strTopic = _T("123"); 59 CString strMsg = _T("111"); 60 System::String ^sTopic = gcnew System::String(strTopic); 61 System::String ^sMsg = gcnew System::String(strMsg); 62 myMqtt->Publish(sTopic, sMsg); 63 }
这样就完成了