UDP数据包失误

时间:2016-05-29 17:07:03

标签: c++ sockets arduino udp coremidi

尽量在这里尽可能地提出我的问题。也许我只是在大声思考。

我的程序应该发送一个大的数据包,大约24字节,但它似乎发射了6个长度的数据包:分别为2,2,4,4,4,8。

从我的Adafruit WICED羽毛传来:

Arduino/Adafruit Serial Monitor

因此,在这种情况下,我的PC发送的数据包为24字节。握手应该返回大小相同的数据包。然而,这就是在另一端获得的东西:

rtpMidi Error Log

如您所见,传入的数据包大小为2,2,4,4,4,然后是8位以上的缓冲区。

我首先想到的是主写函数中有一些东西,它是一个模板:

template<class UdpClass>
inline void AppleMidi_Class<UdpClass>::write(UdpClass& udp, AppleMIDI_InvitationAccepted& ia, IPAddress ip, uint16_t port)
{
   Serial.println("+++++ Writing Packet");
   udp.beginPacket(ip, port);

      udp.write(ia.signature, sizeof(ia.signature));
      udp.write(ia.command, sizeof(ia.command));

      // To appropriate endian conversion
      uint32_t _version = AppleMIDI_Util::toEndian(ia.version);
      uint32_t _initiatorToken = AppleMIDI_Util::toEndian(ia.initiatorToken);
      uint32_t _ssrc = AppleMIDI_Util::toEndian(ia.ssrc);

      // write then out
      udp.write((uint8_t*) ((void*) (&_version)), sizeof(_version));
      udp.write((uint8_t*) ((void*) (&_initiatorToken)), sizeof(_initiatorToken));
      udp.write((uint8_t*) ((void*) (&_ssrc)), sizeof(_ssrc));

      udp.write((uint8_t*) ia.name, strlen(ia.name) + 1);

   udp.endPacket();
   udp.flush();
}

这个模板实际上调用了以下写函数(事实上是6次):

size_t AdafruitUDP::write(const uint8_t* buffer, size_t size)
{
  if (_udp_handle == 0 || _sndIP == 0 || _sndPort == 0) {
    Serial.println("Handle, IP, port == 0 returning");
    return 0;
  }
  //Serial.printf("+++++ Handle: %s IP: %s Send Port: %s\n", _udp_handle, _sndIP, _sndPort);

  sdep_cmd_para_t para_arr[] =
  {
      { .len = 4   , .p_value = &_udp_handle },
      { .len = 4   , .p_value = &_sndIP      },
      { .len = 2   , .p_value = &_sndPort    },
      { .len = size, .p_value = buffer       }
  };
  uint8_t para_count = sizeof(para_arr)/sizeof(sdep_cmd_para_t);

  VERIFY_RETURN(sdep_n(SDEP_CMD_UDP_WRITE, para_count, para_arr, NULL, NULL), 0);
  return size;
}

然后调用:

bool AdafruitSDEP::sdep_n(uint16_t  cmd_id       ,
            uint8_t   para_count   , sdep_cmd_para_t const* para_arr,
            uint16_t* p_result_len , void* p_result)
{
  _errno = FEATHERLIB->sdep_execute_n(cmd_id, para_count, para_arr, p_result_len, p_result);
  handle_error(cmd_id);
  return (ERROR_NONE == _errno);
}

所以,我认为下一个显而易见的问题是:在beginPacket和endPacket期间会发生什么。不多 - 我也没有看到任何回调:

int AdafruitUDP::beginPacket(IPAddress ip, uint16_t port)
{
    _sndIP   = (uint32_t) ip;
    _sndPort = port;

    return 1;
}

/******************************************************************************/
/*!
    @brief  Called after writing UDP data to the remote connection.
*/
/******************************************************************************/
int AdafruitUDP::endPacket()
{
  _sndIP   = 0;
  _sndPort = 0;

    return 1;
}

所以我真正的问题是,在我改变一些奇妙的库之前,是这样的:它看起来好像是用每个appleMidi.write()函数写的标题吗?有没有办法连接appleMidi类的6个写调用?

我认为我在这里走在正确的轨道上,但总是很感激输入。

此致

-Daydreaming at work

1 个答案:

答案 0 :(得分:0)

似乎在您的特定嵌入式系统上,对udp.write()的调用对应于传输的数据包,beginPacket / endPacket仅仅建立并取消传输一个所需的上下文而不是实际描绘边界。

最简单的解决方案可能是将整个数据包组装到缓冲区中,然后在一次调用中写入。

您可能还想将其带到Adafruit支持论坛。