Как выбрать, какой сетевой интерфейс использовать в ESP32

В настоящее время я использую Esp32, который помимо Wi-Fi предоставляет интерфейс Ethernet. Я использую esp-idf v3.3 с FreeRTOS.

Чтобы использовать его, я включил библиотеку esp_eth.h (https://docs.espressif.com/projects/esp-idf/en/release-v3.1/api-reference/ethernet/esp_eth.html#api-reference-phy-lan8720).

Я хотел бы использовать интерфейсы Wi-Fi и Ethernet в зависимости от того, что я хочу сделать, но выбирая, какой из них использовать, есть ли способ?

Практическое использование состоит в том, чтобы получить команду через интерфейс Ethernet (например, сайт для проверки связи), проверить связь с сервером через интерфейс Wi-Fi и ответить интерфейсу Ethernet на результат проверки связи. Как я могу выбрать, какой интерфейс использовать (я не хочу, чтобы пинг выполнялся через Ethernet или чтобы ответ шел через Wi-Fi).

@edit: я нашел метод netif_set_default (struct netif * netif), но я не знаю, лучший ли это способ выбрать интерфейс для использования для конкретного действия (я должен переключаться с одного интерфейса на другой)


person Seriousl Lancerl    schedule 10.02.2020    source источник


Ответы (1)


Просто получите IP-адрес интерфейса Ethernet, затем привяжите сокет к этому IP-адресу.

    struct in_addr iaddr = {0};
#if USE_ANY_IF
    // Bind the socket to any address
    iaddr.s_addr = htonl(INADDR_ANY); 
#else
    // bind only to the Ethernet interface
    tcpip_adapter_ip_info_t ip_info = {0};
    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip_info);
    inet_addr_from_ip4addr(&iaddr, &ip_info.ip);
#endif

Затем используйте его для привязки сокета, например:

static int create_multicast_ipv4_socket(struct in_addr bind_iaddr)
{
    struct sockaddr_in saddr = {0};
    int sock = -1;
    int err = 0;
    char addrbuf[32] = {0};

    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock < 0)
    {
        ESP_LOGE(V4TAG, "Failed to create socket. Error %d", errno);
        return -1;
    }

    saddr.sin_addr.s_addr = bind_iaddr.s_addr; // what interface IP to bind to.  Can be htonl(INADDR_ANY)
    saddr.sin_family = PF_INET;
    saddr.sin_port = htons(UDP_PORT);

    inet_ntoa_r(saddr.sin_addr.s_addr, addrbuf, sizeof(addrbuf) - 1);
    ESP_LOGI(TAG, "Binding to interface %s...", addrbuf);
    err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
    if (err < 0)
    {
        ESP_LOGE(V4TAG, "Failed to bind socket. Error %d", errno);
        goto err;
    }

    // Assign multicast TTL (set separately from normal interface TTL)
    uint8_t ttl = MULTICAST_TTL;
    setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(uint8_t));
    if (err < 0)
    {
        ESP_LOGE(V4TAG, "Failed to set IP_MULTICAST_TTL. Error %d", errno);
        goto err;
    }

    // All set, socket is configured for sending
    return sock;

err:
    close(sock);
    return -1;
}
person phatpaul    schedule 10.09.2020