Я пытаюсь настроить несколько подключенных станций ESP32 через одну точку доступа ESP32. Самый простой способ сделать это - отправить один широковещательный UDP-пакет на номер 255.255.255.255. Однако мои станции, которые слушают через открытый порт UDP, вообще не получают широковещательные данные. Есть ли что-то еще, что мне нужно настроить на станции / точке доступа, чтобы это стало возможным?

Я немного прочитал, и похоже, что lwip / opt.h мог запрещать обнаружение широковещательных пакетов, но после установки IP_SOF_BROADCAST и IP_SOF_BROADCAST_RECV я не заметил разницы.

Вот моя текущая задача прослушивания UDP на станции:

static void udp_listen_task(void *pvParameters)
{

    while (1) {

        struct sockaddr_in dest_addr;
        dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(PORT);
        int addr_family = AF_INET;
        int ip_protocol = IPPROTO_IP;
        inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1);


        int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        //ESP_LOGI(TAG, "Socket created");

        int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
        if (err < 0) {
            ESP_LOGE(TAG, "Socket unable to bind: err %d", err);
        }

        while (1) {

            struct sockaddr_in6 source_addr; 
            socklen_t socklen = sizeof(source_addr);
            int len = recvfrom(sock, &controller_msg, sizeof(controller_msg), 0, (struct sockaddr *)&source_addr, &socklen);

            //Error occurred during receiving
            if (len < 0) {
                ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
                break;
            }
            // Data received
            else {

                // Get the sender's ip address as string
                if (source_addr.sin6_family == PF_INET) {
                    inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
                } else if (source_addr.sin6_family == PF_INET6) {
                    inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1);
                }

                // Post event to act on message
                xEventGroupSetBits(conn_evt, CONN_EVT_UDP_RECEIVED);

            }
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}
0
Kureigu 8 Фев 2021 в 17:26

1 ответ

Лучший ответ

Похоже, в вашем слушающем сокете отсутствует опция SO_BROADCAST. После создания сокета вам понадобится что-то вроде этого:

int bc = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc)) < 0) {
    ESP_LOGE(TAG, "Failed to set sock options: errno %d", errno);
    closesocket(sock);
    break;
}

Взгляните на этот пример

Подсказка: если это не помогает, возможно, вам также потребуется быстрая проверка, чтобы убедиться, что отправитель действительно осуществляет широковещательную рассылку. Подключите компьютер к той же сети Wi-Fi и запустите WireShark, чтобы увидеть UDP-пакеты в воздухе.

1
Tarmo 9 Фев 2021 в 13:25