首页 文章

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

提问于
浏览
2

我刚从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上的新连接客户端上的Socket读取错误(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 回答

  • 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.因此,WiFiClient :: status返回true,而不是未使用的Socket的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中的断开连接吗?

  • 0

    差不多一年半之后,我遇到了同样的问题 . 删除

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

    来自PubSubClient正文连接方法的_client-> stop()为我解决了这个问题 . 但是,我不确定这实际上是一个解决方案,还是只是一个非常脏的快速黑客来解决问题 .

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

相关问题