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

时间:2013-12-02 23:27:04

标签: 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:1207

Mosquitto经纪人表示: 从10.0.0.115开始的新连接 客户端上的套接字读取错误(null),断开连接。

在我开始浏览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 ++工具集进行编译。

我要喝啤酒了!

2 个答案:

答案 0 :(得分:3)

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

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

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

事实证明,WiFi.cpp中存在一个错误,即Arduino WiFi代码。这是代码:

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中的断开连接?

答案 1 :(得分:0)

将近一年半之后,我遇到了同样的问题。删除

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

来自PubSubClient连接方法的_client-> stop()正手为我解决了这个问题。但是,我不确定这是否真的是一个解决方案,或者只是一个非常脏的快速黑客来解决问题。

你做了什么来解决这个问题 - 你对上述问题的解释很好,但我无法轻易提取解决方案; - )