MQTT客户端连接CrystalMQ鉴权报错:Unexpected Maximum QoS value:2 求解决方案
使用以下MQTTnet配置连接CrystalMQ Broker:
_options = new MqttClientOptionsBuilder() .WithClientId(ClientID) .WithTcpServer(Globals.BROKER_ADDRESS, Globals.BROKER_PORT) .WithCredentials(Globals.BROKER_USER, Globals.BROKER_PASSWORD) .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500) // 使用MQTT 5.0版本 .WithTlsOptions(o => { o.UseTls(true); o.WithAllowUntrustedCertificates(false); o.WithIgnoreCertificateChainErrors(false); o.WithIgnoreCertificateRevocationErrors(false); o.WithCertificateValidationHandler(_ => true); Assembly assembly = Assembly.GetExecutingAssembly(); byte[]? certPubicKeyData = null; using (MemoryStream mem = new()) { assembly.GetManifestResourceStream("MqttClient.Certs.client.key")?.CopyTo(mem); certPubicKeyData = mem.ToArray(); } byte[]? certClientData = null; using (MemoryStream mem = new()) { assembly.GetManifestResourceStream("MqttClient.Certs.client.crt")?.CopyTo(mem); certClientData = mem.ToArray(); } byte[]? certRootData = null; using (MemoryStream mem = new()) { assembly.GetManifestResourceStream("MqttClient.Certs.root.crt")?.CopyTo(mem); certRootData = mem.ToArray(); } var rootCert = new X509Certificate2(certRootData); var clientCert = new X509Certificate2(certClientData); //var clientKey= new X509Certificate2(certPubicKeyData); o.WithClientCertificates([rootCert, clientCert]); o.WithSslProtocols(System.Security.Authentication.SslProtocols.Tls12); }) .WithKeepAlivePeriod(TimeSpan.FromSeconds(60)) .WithWillQualityOfServiceLevel(MqttQualityOfServiceLevel.ExactlyOnce) .WithCleanStart(true) .WithSessionExpiryInterval(Globals.BROKER_SESSION_INTERVAL) .Build();
连接触发Disconnected处理器,抛出异常:
Error while authenticating. Unexpected Maximum QoS value: 2
已尝试将遗嘱QoS改为MqttQualityOfServiceLevel.AtLeastOnce,问题依旧。询问是否存在无需修改MQTTnet源码的解决办法。
以下是几个无需修改MQTTnet源码的可行方案:
降级MQTT协议版本:将协议版本从MQTT 5.0改为3.1.1,部分Broker对MQTT 5.0的QoS协商支持不完善,降级后可规避该问题。修改配置中的协议版本行:
.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V311)强制设置客户端最大QoS等级:在配置中添加
.WithMaximumQoS()方法,限制客户端使用的最大QoS为Broker支持的等级(比如AtLeastOnce或AtMostOnce),避免协商时出现Broker不支持的QoS值:.WithMaximumQoS(MqttQualityOfServiceLevel.AtLeastOnce)检查Broker配置:确认CrystalMQ Broker是否开启了QoS 2的支持,或者是否存在全局的最大QoS限制。如果Broker本身不支持QoS 2,即使客户端设置更低的QoS,握手时的协商逻辑仍可能触发该错误,需在Broker端调整配置。
移除遗嘱配置后重试:暂时移除遗嘱相关的配置项,先尝试建立基础连接,确认连接正常后再重新配置遗嘱。如果移除遗嘱后连接成功,说明遗嘱的QoS设置与Broker的QoS限制存在冲突,可尝试使用更低的遗嘱QoS(如AtMostOnce)。
内容的提问来源于stack exchange,提问作者jstuardo

