0

我正在开发基于 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;
}
4

1 回答 1

-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

于 2018-07-03T17:34:24.007 回答