我在 C# 中创建了一个Mqtt.NetWindows 服务,使用Framework 4.6.1.
我本地 Win 10 机器上的服务运行完美,向/从 EMQX Broker 发布/订阅消息。 然而,一旦我将我的 x64 发布版本部署到另一个盒子,就不再有与 Broker 的连接。 我记录了很多调试消息,但没有错误。
这是 EMQX Monitor UI 与我的 3 个客户端连接(我的本地 WinSvc、一个 TS 浏览器连接和 EMQX 云测试客户端)的样子:
我正在使用此 .Net 代码作为我的 Win 服务代码(框架 4.6.1)的指南
我所有的参数都来自我项目的 app.config 文件
<add key="MqttBrokerAddress" value="THE-BROKER.emqxsl.com" />
<!--defaults are 1883(mqtt), 8083(ws) 8084(wss)-->
<add key="MqttPort" value="8084" />
<add key="MqttProtocol" value="wss" />
<add key="QualityOfService" value="0"/>
<!-- certificate required for TLS over wss (port value shuold be 8084)-->
<add key="UseTlsCertificate" value="true" />
<add key="CertificateFileName" value="MY-CERTIFICATE.pfx" />
<add key="CertificatePswd" value="......" />
public void CreateThreadAndRun()
{
Thread m_Thread = new Thread(new ThreadStart(StartPublisherAndSubscriber));
m_Thread.SetApartmentState(ApartmentState.STA);
m_Thread.Name = "MT";
m_Thread.Priority = ThreadPriority.Highest;
m_Thread.Start();
}
private void StartPublisherAndSubscriber()
{
StartSubscriber();
StartPublisher();
}
public async void StartPublisher()
{
var mqttFactory = new MqttFactory();
this.managedMqttClientPublisher = mqttFactory.CreateManagedMqttClient();
// If tls is enabled in app.config, we use wss with cert file
if (MqttUseTls)
{
var managedClientOptions = WsSecureClientOptions();
await this.managedMqttClientPublisher.StartAsync(managedClientOptions);
}
else
{
var insecureOptions = WsInsecureOptions();
await this.managedMqttClientPublisher.StartAsync(
new ManagedMqttClientOptions
{
ClientOptions = insecureOptions
});
}
applog.Debug($"In StartPublisher()");
Publish(defaultMessage + " - " + this.hostName, this.topicThisHost);
}
public ManagedMqttClientOptions WsSecureClientOptions()
{
string assemblyPath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(MqttService)).CodeBase);
// Building out the secure wss url (both pfx/crt certificate file types appear to work here)
var url = $"{mqttBrokerAddress}:{mqttPort}/mqtt";
X509Certificate2 x509Cert = null;
var file = CertificateFileName;
var filePath = Path.Combine(assemblyPath, file).Remove(0, 6);
// pfx file contains both pub and priv keys (needs pswd); crt file only has pub key (no pswd req'd)
if (Path.GetExtension(CertificateFileName.ToLower()) == ".pfx") {
// using a PFX cert file via the X509 class
x509Cert = new X509Certificate2(filePath, CertificatePwd);
}
else if (Path.GetExtension(CertificateFileName.ToLower()) == ".crt")
{
x509Cert = new X509Certificate2(filePath);
}
//var caFile = "broker.emqx.io-ca.crt"; // PULLING FROM APP.CONFIG
//var certFilePath = Path.Combine(assemblyPath, caFile).Remove(0, 6);
var clientOptionsBldr = new MqttClientOptionsBuilder()
.WithWebSocketServer(url)
.WithCredentials(mqttClientUser, mqttClientPswd)
.WithClientId(clientId)
.WithCleanSession()
.WithCredentials(mqttClientUser, mqttClientPswd)
.WithTls(
new MqttClientOptionsBuilderTlsParameters()
{
UseTls = true,
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
Certificates = new List<X509Certificate2>() { x509Cert}
});
ManagedMqttClientOptions managedClientOptions = null;
try
{
applog.Debug($"In WsSecureClientOptions(), about to Build Publisher - ${url}");
managedClientOptions = new ManagedMqttClientOptionsBuilder()
.WithClientOptions(clientOptionsBldr)
.Build();
}
catch (Exception ex)
{
applog.Error("CERT ERROR ! Exception in WsSecureClientOptions() " + ex.Message);
}
return managedClientOptions;
}