arduino - Mosquitto套接字读取错误Arduino客户端

标签 arduino mqtt mosquitto

我刚刚从 Github 下载了最新的 Arduino 库代码,它破坏了我的 MQTT 客户端程序。我在 Arduino 上使用 PubSubClient 1.91,在 Mac OSX 上使用 Mosquitto 1.1.2(Build 2013-03-07)。 (我还在 Windows 7 上对 Mosquitto 进行了测试,同样的问题。)

提供的 Mosquitto 客户端工作正常(Mac 到 Windows,Windows 到 Mac),因此来自 Arduino 端的内容存在一些问题。 wireshark 跟踪显示 Arduino 客户端发送以下数据包:

10:15:ff:ff:4d:51:49:73:64:70:03:02:00:0f:00:07:41:72:64:75:69:6e:6f

Mosquitto 经纪人显示: 来自 10.0.0.115 的新连接 客户端上的套接字读取错误(空),断开连接。

在我开始浏览 MQTT 规范之前,有人能看出正在发送的数据包有什么问题吗?这一定与新的 Arduino 库代码有关...

*更新 经过进一步调查,这似乎是 avr-g++ 的代码生成问题,尽管生活经验告诉我事实并非如此。以下是 PubSubClient.cpp 中的代码片段

boolean PubSubClient::connect(char *id, char *user, char *pass, char* willTopic,     uint8_t willQos, uint8_t willRetain, char* willMessage) {
   if (!connected()) {
      int result = 0;

      if (domain != NULL) {
        result = _client->connect(this->domain, this->port);
      } else {
        result = _client->connect(this->ip, this->port);
      }

      if (result) {
         nextMsgId = 1;
         uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};
//         d[0] = 0;
//         d[1] = 6;
         Serial.print("d[0]="); Serial.println(d[0],HEX);

现在,上面的 Serial.print 的结果是 0xFF !!!因此,uint8_t 数组未正确初始化。 @knoleary 你指向坏 FF 字节的指针引导我到了这个。

如果我现在取消上面两行的注释,并手动将前 2 个字节初始化为 0 和 6,则一切正常,并且我的程序可以与 Mosquitto 愉快地通信。

我已经查看了生成的代码,但我不是 Atmel 专家。

有人知道为什么会这样吗?

我正在 Eclipse 中使用 Arduino 1.05 的 AVR-G++ 工具集进行编译。

我要去喝啤酒了!

最佳答案

好的,我找到了。这是一个相对微妙的错误。本质上,当编译以下行源代码时;

    uint8_t d[9] = { 0x00, 0x06, 'M','Q','I','s','d','p',MQTTPROTOCOLVERSION};

这 9 个字节作为常量存储在图像的数据部分中。在运行时,一个小循环将 9 个字节复制到数组 (d[]) 通过查看组合的汇编器/源列表,我可以看到 9 个字节在数据部分中的存储位置,然后定期打印它们,直到我发现什么覆盖了它们。 (我知道有点原始!)

事实证明,Arduino WiFi 代码 WiFi.cpp 中存在错误。代码如下:

uint8_t WiFiClient::connected() {

  if (_sock == 255) {
    return 0;
  } else {
    uint8_t s = status();

    return !(s == LISTEN || s == CLOSED || s == FIN_WAIT_1 ||
                    s == FIN_WAIT_2 || s == TIME_WAIT ||
                    s == SYN_SENT || s== SYN_RCVD ||
                    (s == CLOSE_WAIT));
  }
}

事实证明 _sock 变量实际上是这样初始化的:

WiFiClient::WiFiClient() : _sock(MAX_SOCK_NUM) {
}

并且 MAX_SOCK_NUM 是 4,而不是 255。因此,对于未使用的 Socket,WiFiClient::status 返回 true,而不是 false。

该方法由 MQTT 客户端调用,如下所示:

boolean PubSubClient::connected() {
   boolean rc;
   if (_client == NULL ) {
      rc = false;
   } else {
      rc = (int)_client->connected();
      if (!rc) _client->stop();
   }
   return rc;
}

并且,由于 _client->connected() 方法错误地返回 true,因此调用了 _client_stop() 方法。这导致写入不存在的套接字数组元素,因此覆盖了我的字符串数据。

@knolleary,我想知道,您的 PubSubClient::connected() 方法断开连接是否有任何具体原因?我在循环中使用::connected 方法来检查我是否仍然连接,当然,这会导致我每次循环时都会断开连接/重新连接。我们是否有机会让连接返回 true/false ,并在 PuBSubClient::connect 中处理断开连接?

关于arduino - Mosquitto套接字读取错误Arduino客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20339952/

相关文章:

c++ - 我可以使用 GT511C1 代替 GT511C3 指纹扫描仪吗?

automation - 使用 Arduino 进行照明控制

docker - 无法订阅Docker Eclipse-Mosquitto Broker

c++ - mbed 中的 Hello World MQTT 程序

azure - IotHubClientTransientException : Transient error occured, 请重试

mysql - mqtt 代理 1.4.1 带有 auth 插件,后端 mysql,无法 sub/pub,用户名或密码错误

mysql - Arduino + MySql + MySqlIO 编译时出错

c++ - Arduino Nano:使用串行输入时,通过计时器进行的A4988步进控制不稳定

mqtt - IOT Mosquitto mqtt 如何在本地主机上测试

c++ - 如何在 C++ 中使用 Mosquitto 发布文件?