客户端在尝试执行连接时已断开连接

The client has been disconnected while trying to perform the connection

尝试在本地连接到 Mosquitto MQTT 队列 运行 时,出现以下错误。

Unhandled exception. System.AggregateException: One or more errors occurred. (The client  has been disconnected while trying to perform the connection)
 ---> System.Net.Mqtt.MqttClientException: The client  has been disconnected while trying to perform the connection
   at System.Net.Mqtt.Sdk.MqttClientImpl.ConnectAsync(MqttClientCredentials credentials, MqttLastWill will, Boolean cleanSession)

我在设置 System.Net.Mqtt.MqttClient 时使用默认选项。

var config = new MqttConfiguration() {
  Port = 1883
};
var client = MqttClient.CreateAsync("localhost", config).Result;
var sessionState = client.ConnectAsync(
                new MqttClientCredentials(clientId: "camerasim")).Result;

Mosquitto MQTT 日志中出现以下错误。

1644497589: New connection from 172.17.0.1:56792 on port 1883.

1644497589: New client connected from 172.17.0.1:56792 as camerasim (p2, c0, k0).

1644497589: Bad socket read/write on client camerasim: Invalid arguments provided.

在设置 MqttConfiguration.

时,通过更改默认值 KeepAliveSecs 属性,我能够成功建立连接
var config = new MqttConfiguration() {
  KeepAliveSecs = 1,
  Port = 1883
};

您看到的错误很可能是 change 在 Mosquitto 2.0.12 中生成的结果:

Fix max_keepalive not applying to MQTT v3.1.1 and v3.1 connections. These clients are now rejected if their keepalive value exceeds max_keepalive. This option allows CVE-2020-13849, which is for the MQTT v3.1.1 protocol itself rather than an implementation, to be addressed.

2.0.9 中的一个变化也起作用了:

Fix max_keepalive option not applying to clients connecting with keepalive set to 0. Closes #2117.

进行这些更改是为了解决 MQTT 协议本身允许拒绝服务攻击的问题 (CVE-2020-13849)。

max_keepalive 的默认值为 65535,因此此更改意味着尝试将保持活动设置为 0(意味着没有保持活动)的连接将失败,除非 mosquitto.conf 指定 max_keepalive 0。不幸的是,记录的错误 (Bad socket read/write on client XXXXXYYYYY: Invalid arguments provided.) 并没有真正突出原因。

有两种可用的解决方案:

  • mosquitto.conf 中指定 max_keepalive 0(Mosquitto 2.0.13 或更高版本)。
  • 连接时指定 1 到 65535 之间的保持活动状态。在 xamarin/mqtt 中,这意味着将 KeepAliveSecs 添加到您的配置中;这个defaults to 0.

请注意,设置 KeepAliveSecs = 1(根据您的回答)将允许您连接,但对于大多数用户来说可能有点短(KeepAliveSecs = 60 可能更合适)。例如

var configuration = new MqttConfiguration {
    Port = 1883,
    KeepAliveSecs = 60,
    WaitTimeoutSecs = 2,
};

我知道您已经找到了解决方案,但由于它可能会影响到其他人,所以我认为有必要解释一下问题的根本原因。许多 MQTT 库默认保持活动状态为 0,因此会受到影响(例如 Go Paho 有一个 issue logged)。