本章节主要介绍用 C#
实现 MQTT
的订阅和发布。
分为 无加密模式 和 单向认证模式。
测试环境为本机。
准备工作:
Mqtt
代理端。安装有 mosquitto
的电脑。关于mosquitto在Windows上的安装请参考MQTT代理Mosquitto在Windows上的安装
证书 (证书只在加密模式下需要)。加密模式下订阅和发布需要证书。证书生成参考使用OpenSSL创建证书
Mqtt
协议的实现库。本文使用的实现库为 M2Mqtt
。github 地址 https://github.com/eclipse/paho.mqtt.m2mqtt
本文使用开发工具为 Visual Studio 2010
保持安装后默认配置即可
Visual Studio
中新建控制台应用程序 NormalPublisher
,添加 M2Mqtt
引用。Program
类中如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace NormalPublisher
{
class Program
{
static void Main(string[] args)
{
string content = "hello mqtt";
string topic = "/home/temperature";
string host = "127.0.0.1";
// 实例化Mqtt客户端
MqttClient client = new MqttClient(host);
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
string strValue = Convert.ToString(content);
// 发布消息主题 "/home/temperature" ,消息质量 QoS 2
client.Publish(topic, Encoding.UTF8.GetBytes(strValue), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
Console.WriteLine(string.Format("publisher,topic:{0},content:{1}", topic, content));
}
}
}
Visual Studio
中新建控制台应用程序 NormalSubscriber
,添加 M2Mqtt
引用。Program
类中如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using System.Net;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace NormalSubscriber
{
class Program
{
static void Main(string[] args)
{
string topic = "/home/temperature";
string host = "127.0.0.1";
// 实例化Mqtt客户端
MqttClient client = new MqttClient(host);
// 注册接收消息事件
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
// 订阅主题 "/home/temperature", 订阅质量 QoS 2
client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
}
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// 打印订阅的发布端消息
Console.WriteLine(string.Format("subscriber,topic:{0},content:{1}", e.Topic, Encoding.UTF8.GetString(e.Message)));
}
}
}
启动 MQTT
代理端。(订阅端和发布端启动前必须保证代理端已启动)
启动订阅端 NormalSubscriber.exe
启动发布端 NormalPublisher.exe
可以看到,订阅端接收到了发布端发布的消息,消息主题为 /home/temperature
,消息内容为 hello mqtt
单向认证需要根证书和服务端证书
单向认证需要代理端开启SSL/TLS,具体操作需要通过配置mosquitto.conf实现。
关于证书的生成和单向认证 mosquitto.conf
的配置,请参考上一节 证书生成及mosquitto配置
Visual Studio
中新建控制台应用程序 OneWayPublisher
,添加 M2Mqtt
引用。Program
类中如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace OneWayPublisher
{
class Program
{
static void Main(string[] args)
{
string content = "hello mqtt";
string topic = "/home/temperature";
X509Certificate caCert = new X509Certificate(@"D:\cert\demo\ca.crt");
string host = "admin";//根证书中的主机名称。证书中Common Name参数若填写域名或IP,此处应填写域名或IP
MqttClient client = new MqttClient(host, MqttSettings.MQTT_BROKER_DEFAULT_SSL_PORT, true, caCert, MqttSslProtocols.TLSv1_0, new System.Net.Security.RemoteCertificateValidationCallback((rsender, certificate, chain, policyErrors) => { return true; }));
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
string strValue = Convert.ToString(content);
// publish a message on "/home/temperature" topic with QoS 2
client.Publish(topic, Encoding.UTF8.GetBytes(strValue), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
Console.WriteLine(string.Format("publisher,topic:{0},content:{1}", topic, content));
}
}
}
Visual Studio
中新建控制台应用程序 OneWaySubscriber
,添加 M2Mqtt
引用。Program
类中如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using System.Security.Cryptography.X509Certificates;
namespace OneWaySubscriber
{
class Program
{
static void Main(string[] args)
{
string topic = "/home/temperature";
X509Certificate caCert = new X509Certificate(@"D:\cert\demo\ca.crt");//根证书
string host = "admin";//根证书中的主机名称(本样例所有测试均在本机进行,证书创建过程Common Name参数填写的本机名称admin。也可以域名或IP。)
// create client instance
MqttClient client = new MqttClient(host, MqttSettings.MQTT_BROKER_DEFAULT_SSL_PORT, true, caCert, MqttSslProtocols.TLSv1_0, new System.Net.Security.RemoteCertificateValidationCallback((rsender, certificate, chain, policyErrors) => { return true; }));
// register to message received
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
// subscribe to the topic "/home/temperature" with QoS 2
client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
}
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// handle message received
Console.WriteLine(string.Format("subscriber,topic:{0},content:{1}", e.Topic, Encoding.UTF8.GetString(e.Message)));
}
}
}
启动 MQTT
代理端。(订阅端和发布端启动前必须保证代理端已启动)
启动订阅端 OneWaySubscriber.exe
启动发布端 OneWayPublisher.exe
运行结果截图如下:
可以看到,订阅端接收到了发布端发布的消息,消息主题为 /home/temperature
,消息内容为 hello mqtt
由于采取了单向认证,数据在传输过程中均为密文。订阅端接收到消息后,经过证书中的对称加密算法解密,就得到了我们需要的数据。
关于SSL单向认证和双向认证原理可以参考 https://edison0663.iteye.com/blog/996526