【问题标题】:ESP32 Multicast UDP High losses (receiving)ESP32 组播 UDP 高损耗(接收)
【发布时间】:2018-07-03 08:32:32
【问题描述】:

我正在开发基于 ESP32 模块的设备,该模块打开了一个 UDP 套接字,仅用于在一个端口(确切地说是 7890)上接收广播数据包。问题是数据丢失率很高 - 大约 90%。我的测试设置是:

  • ESP32 - 通过打开的 UDP 接收任务连接到 WiFi 网络(代码如下)
  • PC 通过 LAN 连接到同一网络,UDP 终端设置为广播到远程:192.168.10.255:7890
  • 手机连接WiFi,UDP终端设为广播到远程:192.168.10.255:7890

当我从 PC 或手机发送内容时,手机和 PC 之间没有数据丢失,但 ESP32 接收到我从两个发送者发送的大约 10% 的数据。如果我在 PC 或手机上从多播更改为单播以将数据发送到 ESP32,它可以正常工作。

我知道 UDP 不保证传输,但是 10% 的效率对我来说似乎是超低的,尤其是当网络繁忙时似乎没有问题,因为 PC 和移动设备一直在接收数据。

您对代码或可以在菜单配置中更改的某些设置有什么建议吗? 目前我的应用程序只有两个任务:

  • WiFi 连接后等待事件的任务
  • UDP 代码如下的任务

更新 04.07.2018 (13:15)

当我不初始化蓝牙时问题消失了。抱歉,我之前没有提到 BT 被初始化,但我一直在我的正常程序中初始化函数,该程序有更多任务(包括 BT),我自己完全忘记了这一点。

无论如何-您认为共享资源存在一些问题还是一些物理干扰?我使用的是面包板上的 ESP32-DevKitC,所以没有额外的屏蔽。


#define PORT_NUMBER 7890
#define BUFLEN 100

void udp_task(void *pvParameter)
{
   struct sockaddr_in clientAddress;
   struct sockaddr_in serverAddress;
   struct sockaddr_in si_other;
   unsigned int slen = sizeof(si_other);
   unsigned int recv_len;
   char buf[BUFLEN];
   int sock;

   printf("UDP Task: Opening..\n");

   int ret;
   ret = UDP_List_Open(&clientAddress, &serverAddress, &sock);

   if(ret == 0)
   {
      printf("UDP Task: Open\n");
   }
   else
   {
      printf("UDP Task: Can't open\n");
   }


    while(1)
    {
        memset(buf,0,100);

        if ((recv_len = recvfrom(sock, buf, 100, 0, (struct sockaddr *) &si_other, &slen)) == -1)
        {
            printf("UDP error\n");
            break;
        }

        sendto(sock, buf, recv_len, 0, (struct sockaddr *)&si_other, sizeof(si_other));

        printf("UDP Task: Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
        printf("UDP Task: Data: %s -- %d\n" , buf, recv_len);
    }

   while(1)
   {
      vTaskDelay(100 / portTICK_RATE_MS);
   }
}


int UDP_List_Open(struct sockaddr_in* clientAddress, struct sockaddr_in* serverAddress, int* sock)
{
    // Create a socket that we will listen upon.
   *sock = socket(AF_INET, SOCK_DGRAM, 0);
   if (*sock < 0)
   {
      printf("UDP List Open: Socket error\n");
      return 1;
   }

   // Bind our server socket to a port.
   serverAddress->sin_family = AF_INET;
   serverAddress->sin_addr.s_addr = htonl(INADDR_ANY);
   serverAddress->sin_port = htons(PORT_NUMBER);
   int rc  = bind(*sock, serverAddress, sizeof(*serverAddress));
   if (rc < 0)
   {
      printf("UDP List Open: Bind error\n");
      return 2;
   }

   return 0;
}

【问题讨论】:

  • BT 和 Wifi 共享天线。在您的情况下,当 BT 获取天线时,您的套接字正在发送并且没有错误,因为您不期待响应,但没有任何东西离开 esp。当 BT 释放天线时,您的 wifi 连接再次发送。我在自动取款机上遇到了同样的问题,正在寻找解决方案。 stackoverflow.com/questions/55865909/…

标签: sockets udp wifi multicast esp32


【解决方案1】:

尽管 UDP 被认为是一劳永逸(与 TCP 不同),但通过 WiFi 的单播 UDP 是可靠的,因为可靠性内置于 WiFi 协议中。但这仅适用于单播,因为有一个已知的接收者。多播 UDP 不可靠,因为没有检查和重试。

当我尝试将多播 UDP 与 ESP8266 一起使用时,我遇到了同样的问题。这让我更深入地研究了这个问题。最后,我使用 UDP 多播进行发现,然后切换到单播 UDP 进行后续传输。

请参阅多播 Wifi 问题说明 https://tools.ietf.org/id/draft-mcbride-mboned-wifi-mcast-problem-statement-01.html

【讨论】:

  • 谢谢,我的想法是一样的:使用服务器广播来发现设备,然后用单播连接它们,但是发现可能需要很长时间,因为这样的损失(例如广播中的 15 秒间隔可能会在 150 秒的发现时间内结束)。我知道多播中的 UDP 不可靠,但在我看来 90% 的数据包错误率 (PER) 似乎太高了,在每篇文章中他们都提到 PER 的 5%、10% 或 15%,但不是 90%。
  • 真的要看具体情况。在该频带上发生了多少活动。无线电的物理位置(两端)。我的测试中有一些模块处于活动状态,有些模块会比其他模块更难。移动收音机改变了一切。
  • 在工作中我们有一个 WiFi 用于测试,一位软件开发人员告诉我,他知道我什么时候在午餐时间使用微波炉,因为 WiFi 停止工作。当您切换到单播时,您会看到不同之处。就无线电传输而言,多播和单播之间没有区别。不同之处在于重试次数。
  • 这既有趣又可怕。无论如何,事实证明蓝牙是造成损失的原因,我不确定是软件问题还是物理问题。
猜你喜欢
  • 2022-11-02
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多