一、背景介绍

随着物联网的兴起,.Net 框架在构建物联网应用程序方面变得越来越流行。微软的 .Net Core 和 .Net 框架为开发人员提供了一组工具和库,以构建可以在 Raspberry Pi、HummingBoard、BeagleBoard、Pine A64 等平台上运行的物联网应用程序。

MQTTnet 是一个实现 MQTT 协议的高性能 .Net 库,在 GitHub 上开源,具有丰富的功能,支持 MQTT 5.0 协议和 TLS/SSL。

本文介绍使用 MQTTnet 库连接到 EMQX Serverless MQTT 消息服务器。

二、准备 MQTT Broker

1、使用 APT 安装 EMQX

# 配置 EMQX APT 源
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash

在这里插入图片描述

# 安装 EMQX 最新版
sudo apt-get install emqx

在这里插入图片描述

# 启动 EMQX
sudo emqx start

在这里插入图片描述

2、EMQX 运行情况检查

netstat -tunlp

在这里插入图片描述

端口说明
1883MQTT/TCP 协议端口
8883MQTT/SSL 协议端口
8083MQTT/WS 协议端口
8084MQTT/WSS 协议端口
18083EMQX Dashboard 端口
4370Erlang 分布式传输端口
5370集群 RPC 端口,默认情况下,每个 EMQX 节点有一个 RPC 监听端口。

3、访问 Dashboard

EMQX 提供了 Dashboard,以方便用户通过 Web 页面管理、监控 EMQX 并配置所需的功能。EMQX 成功启动之后可以通过浏览器打开 http://localhost:18083/

在这里插入图片描述

Dashboard 的默认用户名为 admin,密码为 public,第一次登录成功后会提示修改密码。密码修改完成后,我们也可以在 Settings 页面将 Dahshboard 的语言改为 简体中文

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4、配置认证

EMQX 从 5.0 开始支持在 Dashbaord 配置认证,以方便用户能更加方便、快速的创建安全的 MQTT 服务。我们点击 访问控制 菜单下的 认证 进入认证配置页面,然后点击最右侧的 创建 按钮:

在这里插入图片描述

选择 Password-Based 选项:

在这里插入图片描述

数据库选择 内置数据库

在这里插入图片描述

接下来选择账户类型、加密方式、加盐方式,并点击 创建

在这里插入图片描述

认证创建成功后如下图,接下来我们点击 用户管理 添加用户:

在这里插入图片描述

进入用户管理页面后,我们点击最右侧的 添加 按钮,并在弹出框里设置用户名与密码,之后点击 保存

在这里插入图片描述

在这里插入图片描述

如下图表示创建成功:

在这里插入图片描述

使用 Dashboard 提供的 Websocket 工具来测试认证是否已配置成功,在连接配置里输入刚才创建的用户名与密码,然后点击连接,将会看到右侧弹窗提示已连接:

在这里插入图片描述

使用一个未创建的用户名 test1,点击连接将会看到如下连接失败信息:

在这里插入图片描述

至此,我们已完成了 EMQX 的认证配置,搭建了一台可用于生产环境的单节点 MQTT 服务器。

三、SSL/TLS 证书准备

通常来说,我们会需要数字证书来保证 TLS 通讯的强认证,数字证书的使用本身是一个三方协议,除了通讯双方,还有一个颁发证书的受信第三方,有时候这个受信第三方就是一个 CA。

# 安装 OpenSSL
sudo apt install openssl

首先,我们需要一个自签名的 CA 证书,生成这个证书需要有一个私钥为它签名,可以执行以下命令来生成私钥:

openssl genrsa -out ca.key 2048

这个命令将生成一个密钥长度为 2048 的密钥并保存在 ca.key 中,有了这个密钥,就可以用它来生成 EMQX 的根证书了:

openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.pem

在这里插入图片描述

查看 CA 证书信息(可选):

openssl x509 -in ca.pem -noout -text

在这里插入图片描述

根证书是整个信任链的起点,如果一个证书的每一级签发者向上一直到根证书都是可信的,那个我们就可以认为这个证书也是可信的,有了这个根证书,我们就可以用它来给其他实体签发实体证书了。

除了 CA 证书,实体(在这里指的是 EMQX)也需要一个自己的 Key 对来保证它对自己证书的控制权,生成这个密钥的过程和上面类似:

openssl genrsa -out emqx.key 2048

新建 openssl.cnf 文件:

[req]
default_bits  = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
countryName = CN
stateOrProvinceName = Guangdong
localityName = Dongguan
organizationName = EMQX
commonName = Server certificate
[req_ext]
subjectAltName = @alt_names
[v3_req]
subjectAltName = @alt_names
[alt_names]
IP.1 = BROKER_ADDRESS
DNS.1 = BROKER_ADDRESS
  • req_distinguished_name :根据情况进行修改,
  • alt_names: BROKER_ADDRESS 修改为 EMQX 服务器实际的 IP 或 DNS 地址,例如:IP.1 = 127.0.0.1,或 DNS.1 = broker.xxx.com

在这里插入图片描述

然后以这个密钥和配置签发一个证书请求:

openssl req -new -key ./emqx.key -config openssl.cnf -out emqx.csr

在这里插入图片描述

以根证书来签发 EMQX 的实体证书:

openssl x509 -req -in ./emqx.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out emqx.pem -days 3650 -sha256 -extensions v3_req -extfile openssl.cnf

查看 EMQX 实体证书(可选):

openssl x509 -in emqx.pem -noout -text

在这里插入图片描述

验证 EMQX 实体证书,确定证书是否正确:

openssl verify -CAfile ca.pem emqx.pem
emqx.pem: OK

在这里插入图片描述

准备好证书后,我们就可以启用 EMQX 的 TLS/SSL 功能了。

四、SSL/TLS 启用及验证

在 EMQX 中 mqtt:ssl 的默认监听端口为 8883。

将前文中通过 OpenSSL 工具生成的 emqx.pem、emqx.key 及 ca.pem 文件拷贝到 EMQX 的 certs 目录下,并参考如下配置修改 emqx.conf

sudo cp emqx.key emqx.pem ca.pem /etc/emqx/certs/

在这里插入图片描述

## listener.ssl.$name is the IP address and port that the MQTT/SSL
## Value: IP:Port | Port
listener.ssl.external = 8883## Path to the file containing the user's private PEM-encoded key.
## Value: File
listener.ssl.external.keyfile = etc/certs/emqx.key## 注意:如果 emqx.pem 是证书链,请确保第一个证书是服务器的证书,而不是 CA 证书。
## Path to a file containing the user certificate.
## Value: File
listener.ssl.external.certfile = etc/certs/emqx.pem## 注意:ca.pem 用于保存服务器的中间 CA 证书和根 CA 证书。可以附加其他受信任的 CA,用来进行客户端证书验证。
## Path to the file containing PEM-encoded CA certificates. The CA certificates
## Value: File
listener.ssl.external.cacertfile = etc/certs/ca.pem

在这里插入图片描述

# emqx.conf
listener.ssl.external = 8883
listener.ssl.external.keyfile = "./certs/emqx.key"
listener.ssl.external.certfile = "./certs/emqx.pem"
listener.ssl.external.cacertfile = "./certs/ca.pem"

注意,配置完成需要重启 EMQX !打开 EMQX 的 Dashboard 在 Listeners 页面可以看到在 8883 端口上有一个 ssl 连接:

在这里插入图片描述

MQTT 连接测试:

https://mqttx.app/zh/downloads

当配置完成并重启 EMQX 后,我们使用 MQTT 客户端工具 - MQTTX(该工具跨平台且支持 MQTT 5.0),来验证 TLS 服务是否正常运行。

在这里插入图片描述

sudo dpkg -i MQTTX_1.12.0_amd64.deb

在这里插入图片描述

在这里插入图片描述

在前文中我们配置了认证,所以这里需要注意输入帐号密码,同时开启 SSL/TLS,证书类型选择 CA or Self signed certificates

在这里插入图片描述

连接成功,订阅主题 testtop

在这里插入图片描述

五、创建项目

dotnet new console -f net8.0

在这里插入图片描述

六、安装 MQTTnet 包

注意,这里使用的 MQTTnet 版本为 4.2.0.706 ,并没有使用最新版。

在这里插入图片描述

七、设置连接

要连接到 EMQX Cloud Serverless 服务,需要创建 MqttClientOptionsBuilder 类的实例,并设置必要的选项,如代理地址、端口、用户名和密码。

string broker = "******.emqxsl.com";
int port = 8883;
string clientId = Guid.NewGuid().ToString();
string topic = "Csharp/mqtt";
string username = "emqxtest";
string password = "******";// Create a MQTT client factory
var factory = new MqttFactory();// Create a MQTT client instance
var mqttClient = factory.CreateMqttClient();// Create MQTT client options
var options = new MqttClientOptionsBuilder().WithTcpServer(broker, port) // MQTT broker address and port.WithCredentials(username, password) // Set username and password.WithClientId(clientId).WithCleanSession().Build();

八、使用 TLS/SSL

连接到 EMQX Serverless 时,需要注意的是,它依赖于多租户架构,该架构使多个用户能够共享单个 EMQX 集群,为了保证这种多租户环境内数据传输的安全性和可靠性,需要 TLS,并且如果服务器使用的是自签名证书,则必须从部署概览面板下载相应的 CA 文件,并在连接建立过程中提供。

要添加 TLS 并将证书文件设置为 MqttClientOptionsBuilder 实例,可以使用 WithTls()

string broker = "******.emqxsl.com";
int port = 8883;
string clientId = Guid.NewGuid().ToString();
string topic = "Csharp/mqtt";
string username = "emqxtest";
string password = "******";// Create a MQTT client factory
var factory = new MqttFactory();// Create a MQTT client instance
var mqttClient = factory.CreateMqttClient();// Create MQTT client options
var options = new MqttClientOptionsBuilder().WithTcpServer(broker, port) // MQTT broker address and port.WithCredentials(username, password) // Set username and password.WithClientId(clientId).WithCleanSession().WithTls(o =>{// The used public broker sometimes has invalid certificates. This sample accepts all// certificates. This should not be used in live environments.o.CertificateValidationHandler = _ => true;// The default value is determined by the OS. Set manually to force version.o.SslProtocol = SslProtocols.Tls12; ;// Please provide the file path of your certificate file. The current directory is /bin.var certificate = new X509Certificate("/opt/emqxsl-ca.crt", "");o.Certificates = new List<X509Certificate> { certificate };}).Build();

九、连接到 MQTT 消息服务器

只需使用 MQTT 客户端的 PublishAsync 方法建立连接并开始发送和接收消息。

var connectResult = await mqttClient.ConnectAsync(options);

这里我们使用异步编程,在订阅的同时允许消息发布,防止阻塞。

十、订阅主题

连接到代理后,可以通过检查 ResultCode 的值来验证连接是否成功。如果连接成功,可以订阅主题来接收消息。

if (connectResult.ResultCode == MqttClientConnectResultCode.Success)
{Console.WriteLine("Connected to MQTT broker successfully.");// Subscribe to a topicawait mqttClient.SubscribeAsync(topic);// Callback function when a message is receivedmqttClient.ApplicationMessageReceivedAsync += e =>{Console.WriteLine($"Received message: {Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment)}");return Task.CompletedTask;};
}

十一、发布消息

要向 EMQX Cloud Serverless 消息服务发送消息,请使用 MQTT 客户端的 PublishAsync 方法。以下是循环向消息服务发送消息的示例,每秒发送一条消息:

for (int i = 0; i < 10; i++)
{var message = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload($"Hello, MQTT! Message number {i}").WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build();await mqttClient.PublishAsync(message);await Task.Delay(1000); // Wait for 1 second
}

十二、取消订阅

要取消对消息主题的订阅,请调用:

await mqttClient.UnsubscribeAsync(topic);

十三、断开连接

要断开连接,请调用:

await mqttClient.DisconnectAsync();

十四、完整代码

下面的代码展示了如何连接到服务器、订阅主题以及发布和接收消息。

using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;// string broker = "******.emqxsl.com";
string broker = "127.0.0.1";
int port = 8883;
string clientId = Guid.NewGuid().ToString();
string topic = "Csharp/mqtt";
// string username = "emqxtest";
// string password = "******";string username = "sam";
string password = "0123456789";// Create a MQTT client factory
var factory = new MqttFactory();// Create a MQTT client instance
var mqttClient = factory.CreateMqttClient();// Create MQTT client options
var options = new MqttClientOptionsBuilder().WithTcpServer(broker, port) // MQTT broker address and port.WithCredentials(username, password) // Set username and password.WithClientId(clientId).WithCleanSession().WithTls(o =>{// The used public broker sometimes has invalid certificates. This sample accepts all// certificates. This should not be used in live environments.o.CertificateValidationHandler = _ => true;// The default value is determined by the OS. Set manually to force version.o.SslProtocol = SslProtocols.Tls12;// Please provide the file path of your certificate file. The current directory is /bin.// var certificate = new X509Certificate("/opt/emqxsl-ca.crt", "");var certificate = new X509Certificate("ca.pem", "");o.Certificates = new List<X509Certificate> { certificate };}).Build();// Connect to MQTT broker
var connectResult = await mqttClient.ConnectAsync(options);if (connectResult.ResultCode == MqttClientConnectResultCode.Success)
{Console.WriteLine("Connected to MQTT broker successfully.");// Subscribe to a topicawait mqttClient.SubscribeAsync(topic);// Callback function when a message is receivedmqttClient.ApplicationMessageReceivedAsync += e =>{Console.WriteLine($"Received message: {Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment)}");return Task.CompletedTask;};// Publish a message 10 timesfor (int i = 0; i < 10; i++){var message = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload($"Hello, MQTT! Message number {i}").WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build();await mqttClient.PublishAsync(message);await Task.Delay(1000); // Wait for 1 second}// Unsubscribe and disconnectawait mqttClient.UnsubscribeAsync(topic);await mqttClient.DisconnectAsync();
}
else
{Console.WriteLine($"Failed to connect to MQTT broker: {connectResult.ResultCode}");
}

运行效果:

Connected to MQTT broker successfully.
Received message: Hello, MQTT! Message number 0
Received message: Hello, MQTT! Message number 1
Received message: Hello, MQTT! Message number 2
Received message: Hello, MQTT! Message number 3
Received message: Hello, MQTT! Message number 4
Received message: Hello, MQTT! Message number 5
Received message: Hello, MQTT! Message number 6
Received message: Hello, MQTT! Message number 7
Received message: Hello, MQTT! Message number 8
Received message: Hello, MQTT! Message number 9

在这里插入图片描述

参考文档

  • https://www.emqx.com/zh/blog/connecting-to-serverless-mqtt-broker-with-mqttnet-in-csharp
  • https://www.emqx.com/zh/blog/how-to-install-emqx-mqtt-broker-on-ubuntu
  • https://www.emqx.com/zh/blog/emqx-server-ssl-tls-secure-connection-configuration-guide
  • https://www.emqx.com/zh/blog/enable-two-way-ssl-for-emqx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/97849.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/97849.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/97849.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

突破性能瓶颈:基于腾讯云EdgeOne的AI图片生成器全球加速实践

1. 项目背景与挑战 1.1 开发背景 随着AIGC技术爆发&#xff0c;我们团队决定开发一款多模型支持的AI图片生成器&#xff0c;主要解决以下痛点&#xff1a; 不同AI模型的参数规范不统一生成结果难以系统化管理缺乏企业级的安全水印方案全球用户访问延迟高&#xff0c;中国用户…

一、Java 基础入门:从 0 到 1 认识 Java(详细笔记)

1.1 Java 语言简介与发展历程 Java 是一门面向对象的高级编程语言&#xff0c;以“跨平台、安全、稳定”为核心特性&#xff0c;自诞生以来长期占据编程语言排行榜前列&#xff0c;广泛应用于后端开发、移动端开发、大数据等领域。 1.1.1 起源与核心人物 起源背景&#xff1…

uniapp:根据目的地经纬度,名称,唤起高德/百度地图来导航,兼容App,H5,小程序

1、需要自行申请高德地图的key,配置manifest.json 2、MapSelector选择组件封装 <template><view><u-action-sheet :list="mapList" v-model="show" @click="changeMap"></u-action-sheet></view> </template&…

我对 WPF 动摇时的选择:.NET Framework 4.6.2+WPF+Islands+UWP+CompostionApi

目录 NET Framework 4.6.2的最大亮点 为什么固守462不升级 WPF-开发体验的巅峰 为什么对WPF动摇了 基于IslandsUWP的滤镜尝试 总结 NET Framework 4.6.2的最大亮点 安全性能大提升&#xff1a; 默认启用TLS1.2协议&#xff0c;更安全&#xff0c;它为后续的版本提供了重…

SpringBoot大文件下载失败解决方案

SpringBoot大文件下载失败解决方案 后端以文件流方式给前端接收下载文件,文件过大时出现下载失败的情况或者打开后提示文件损坏,实际是字节未完全读取写入。 针对大文件下载失败的情况,以下是详细的解决方案: 大文件下载失败的主要原因 内存溢出:一次性加载大文件到内存…

torch.gather

torch.gather 介绍 torch.gather(input, dim, index, *, sparse_gradFalse, outNone) → Tensor 沿由 dim 指定的轴收集值。 对于三维张量&#xff0c;输出按如下方式确定&#xff1a; out[i][j][k] input[index[i][j][k]][j][k] # 如果 dim 0 out[i][j][k] input[i][i…

Golang | http/server Gin框架简述

http/server http指的是Golang中的net/http包&#xff0c;这里用的是1.23.10。 概览 http包的作用文档里写的很简明&#xff1a;Package http provides HTTP client and server implementations. 主要是提供http的客户端和服务端&#xff0c;也就是能作为客户端发http请求&a…

Vision Transformer (ViT) :Transformer在computer vision领域的应用(三)

Experiment 上来的一段话就概括了整章的内容。 We evaluate the representation learning capabilities of ResNet, Vision Transformer (ViT), and the hybrid. 章节的一开头就说明了,对比的模型就是 ResNet,CNN领域中的代码模型。 ViT。 上一篇中提到的Hybrid模型,也就是…

5-12 WPS JS宏 Range数组规范性测试

Range()数组是JS宏中不缺少的组成部分,了解Range()数组的特性必不可少,下面我们一起测试一下各种Range()数组。 1.Range()数组特性 单元格区域:Range("a2:m2")与Range("a2","m2")的类型都是:Range/Object,功能都为单元格区域,功能…

uniapp微信小程序保存海报到手机相册canvas

在uniapp中实现微信小程序保存海报到手机相册&#xff0c;主要涉及Canvas绘制和图片保存。以下是关键步骤和代码示例&#xff1a; 一、关键代码展示&#xff1a; 1. 模板配置&#xff1a;页面展示该海报&#xff0c;可直接查看&#xff0c;也可下载保存到手机相册&#xff0c;h…

glib2-2.62.5-7.ky10.x86_64.rpm怎么安装?Kylin Linux RPM包安装详细步骤

一、准备工作 ​确认系统版本​ 这个包是 ky10的&#xff08;也就是 openEuler 20.03 LTS SP3 或类似版本&#xff09;&#xff0c;而且是 ​x86_64 架构&#xff08;就是常见的64位电脑&#xff09;​。 你要先确认你的系统是不是这个版本&#xff0c;不然可能装不上或者出问题…

webrtc之语音活动下——VAD人声判定原理以及源码详解

文章目录前言一、高斯混合模型介绍1.高斯模型举例1&#xff09;定义2&#xff09;举例说明2.高斯混合模型(GMM)1&#xff09;定义2&#xff09;举例说明3&#xff09;一维曲线二、VAD高斯混合模型1.模型训练介绍1&#xff09;训练方法2&#xff09;训练结果2.噪声高斯模型分布1…

【Redis】-- 主从复制

文章目录1. 主从复制1.1 主从复制是怎么个事&#x1f914;1.2 拓扑结构1.2.1 一主一从拓扑1.2.2 一主多从拓扑1.2.3 树形拓扑1.3 主从复制原理1.3.1 复制过程1.3.2 数据同步PSYNC1.3.2.1 replicationid/replid (复制id)1.3.2.2 复制偏移量维护1.3.3 psync运行流程1.3.4 全量复制…

开源炸场!阿里通义千问Qwen3-Next发布:80B参数仅激活3B,训练成本降90%,长文本吞吐提升10倍​

开源炸场&#xff01;阿里通义千问Qwen3-Next发布&#xff1a;80B参数仅激活3B&#xff0c;训练成本降90%&#xff0c;长文本吞吐提升10倍​ 开源世界迎来震撼突破&#xff01; 通义千问团队最新发布的Qwen3-Next架构&#xff0c;以其独创的"小而精"设计理念&#x…

【C++入门】C++基础

目录 1. 命名空间 1.1 命名空间的创建和使用 2. 输入输出 2.1 输出 2.2 输入 3. 缺省参数 3.1 全缺省 3.2 半缺省 4.函数重载 4.1 为什么C支持重载而C语言不支持&#xff1f; 4.1.2 编译的四个过程 4.2 extern是什么 5.引用 5.1 引用的特性 5.1.1 引用的“隐式类…

如何往mp4视频添加封面图和获取封面图?

前言&#xff1a;大家好&#xff0c;之前有给大家分享过mp4录像的方案&#xff0c;今天给大家分享的内容是&#xff1a;如何在添加自定义的封面图到mp4里面去&#xff0c;以及在进入回放mp4视频列表的时候&#xff0c;怎么获取mp4视频里面的封面图&#xff0c;当然这个获取到的…

你的第一个Transformer模型:从零实现并训练一个迷你ChatBot

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;注册即送-H卡级别算力&#xff0c;80G大显存&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生更享专属优惠。 引言&#xff1a;破除神秘感&#xff0c;拥抱核心思想 …

【20期】沪深指数《实时交易数据》免费获取股票数据API:PythonJava等5种语言调用实例演示与接口API文档说明

​ 随着量化投资在金融市场的快速发展&#xff0c;高质量数据源已成为量化研究的核心基础设施。本文将系统介绍股票量化分析中的数据获取解决方案&#xff0c;涵盖实时行情、历史数据及基本面信息等关键数据类型。 本文将重点演示这些接口在以下技术栈中的实现&#xff1a; P…

RabbitMQ如何保障消息的可靠性

文章目录什么是消息可靠性&#xff1f;RabbitMQ消息可靠性的三个维度1. 生产者到Exchange的可靠性2. Exchange到Queue的可靠性3. Queue到消费者的可靠性核心机制详解Publisher Confirm机制消息持久化Mandatory参数消费者确认机制&#xff08;ACK&#xff09;最佳实践建议1. 合理…

二十、DevOps落地:Jenkins基础入门(一)

二十、DevOps落地&#xff1a;Jenkins基础入门&#xff08;一&#xff09; 文章目录二十、DevOps落地&#xff1a;Jenkins基础入门&#xff08;一&#xff09;1、DevOps初识1.1 什么是DevOps1.2 DevOps相关工具链1.3 什么是CICD&#xff1f;1.4 持续集成CI介绍1.5 持续交付和持…