不断重连wifi后,无法创建socket求助

jinkai
Posts: 11
Joined: Fri Jun 16, 2023 2:24 am

不断重连wifi后,无法创建socket求助

Postby jinkai » Wed Sep 13, 2023 9:04 am

idf版本:V5.0.2
开发板:esp-32
问题描述:
我使用两台esp32,不断重复以下步骤:连接wifi--》创建TCP server --》作为TCP client向另一台esp32发送数据 --》 断开 wifi
经过五轮左右循环后出现以下两个报错:

Code: Select all

TCP SERVER: Unable to create socket: errno 23

 TCP client: Unable to create socket: errno 23
TCP client与TCP server 具体代码如下:

Code: Select all

/**
 * @brief       发送 wifi 数据, wifi 发送数据指令格式:
 *              |-- 目的地址长度(1 byte) --|-- 目的地址(n bytes) --|-- 信息长度(2 bytes) --|-- 目的地址长度(n bytes) --|
 * @param[in]   data - 发送数据内容
 * @param[in]   len - 发送数据内容的长度
 */
int tcpClientSendDataToRemote(uint8_t *data, const uint16_t len)
{
    char host_ip[17] = {0};
    int addr_family = 0;
    int ip_protocol = 0;
    int sendDataLen = 0;
    int toWrite = len;
    int written = 0;
    int sock = 0;
    int err = 0;

    if (NULL == data || len < 11 || WifiStation.status != WIFI_STATUS_CONNECTED)
    {
        return -1;
    }

    memcpy((uint8_t *)host_ip, (uint8_t *)(data + 1), data[0]);

    struct sockaddr_in dest_addr;
    dest_addr.sin_addr.s_addr = inet_addr(host_ip);
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(PORT);
    addr_family = AF_INET;
    ip_protocol = IPPROTO_IP;

    sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (sock < 0)
    {
        ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        goto failed;
    }
    ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);

    struct timeval timeout;
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    err = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
    if (err != 0)
    {
        goto failed;
    }

    err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
    if (err != 0)
    {
        ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
        goto failed;
    }
    ESP_LOGI(TAG, "Successfully connected");

    // struct linger link;
    // link.l_onoff = 1;
    // link.l_linger = 5;
    // err = setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger));
    // if (err != 0)
    // {
    //     ESP_LOGE(TAG, "SO_LINGER errno %d", errno);
    //     goto failed;
    // }

    while (toWrite > 0)
    {
        // written = send(sock, (data + 1 + data[0] + 2 + (sendDataLen - toWrite)), toWrite, 0);
        written = send(sock, (data + len - toWrite), toWrite, 0);
        if (written < 0) {
            ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
            goto failed;
        }
        toWrite -= written;
    }

    if (sock != -1)
    {
        ESP_LOGW(TAG, "Shutting down socket");
        printf("************ %s(%d) sock:%d\n", __func__, __LINE__, sock);
        shutdown(sock, 0);

        // struct linger link;
        // link.l_onoff = 1;
        // link.l_linger = 5;
        // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger));

        close(sock);
        printf("************ %s(%d) sock:%d\n", __func__, __LINE__, sock);
    }
    return 0;

failed:
    if (sock != -1)
    {
        printf("************ %s(%d) sock:%d\n", __func__, __LINE__, sock);
        shutdown(sock, 0);

        // struct linger link;
        // link.l_onoff = 1;
        // link.l_linger = 5;
        // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger));

        close(sock);
        printf("************ %s(%d) sock:%d\n", __func__, __LINE__, sock);
    }

    return -1;
}

/**
 * @brief       wifi 接收任务
 */
static void tcpServeTask(void *pvParameters)
{
    char addr_str[128];
    int addr_family = (int)pvParameters;
    int ip_protocol = 0;
    int keepAlive = 1;
    int keepIdle = KEEPALIVE_IDLE;
    int keepInterval = KEEPALIVE_INTERVAL;
    int keepCount = KEEPALIVE_COUNT;
    struct sockaddr_storage dest_addr;
    int err = 0;

    if (addr_family == AF_INET)
    {
        struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
        dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr_ip4->sin_family = AF_INET;
        dest_addr_ip4->sin_port = htons(PORT);
        ip_protocol = IPPROTO_IP;
    }

    listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (listen_sock < 0)
    {
        ESP_LOGE(SERVER_TAG, "Unable to create socket: errno %d", errno);
        goto CLEAN_UP;
    }

    int opt = 1;
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    ESP_LOGI(SERVER_TAG, "Socket created");

    err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (err != 0)
    {
        ESP_LOGE(SERVER_TAG, "Socket unable to bind: errno %d", errno);
        ESP_LOGE(SERVER_TAG, "IPPROTO: %d", addr_family);
        goto CLEAN_UP;
    }
    ESP_LOGI(SERVER_TAG, "Socket bound, port %d", PORT);

    struct linger link;
    link.l_onoff = 1;
    link.l_linger = 5;
    err = setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger));
    if (err != 0)
    {
        ESP_LOGE(SERVER_TAG, "SO_LINGER errno: %d", errno);
        goto CLEAN_UP;
    }
    ESP_LOGI(SERVER_TAG, "Start listen");

    err = listen(listen_sock, 1);
    if (err != 0)
    {
        ESP_LOGE(SERVER_TAG, "Error occurred during listen: errno %d", errno);
        goto CLEAN_UP;
    }

    while (1)
    {

        ESP_LOGI(SERVER_TAG, "Socket listening");

        struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
        socklen_t addr_len = sizeof(source_addr);
        int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
        if (sock < 0)
        {
            ESP_LOGE(SERVER_TAG, "Unable to accept connection: errno %d", errno);
            goto CLEAN_UP;
        }

        // Set tcp keepalive option
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
        // Convert ip address to string
        if (source_addr.ss_family == PF_INET)
        {
            inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
        }

        ESP_LOGI(SERVER_TAG, "Socket accepted ip address: %s", addr_str);

        do_retransmit(sock);

        shutdown(sock, 0);

        // struct linger link;
        // link.l_onoff = 1;
        // link.l_linger = 5;
        // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger));

        close(sock);
    }

CLEAN_UP:
        printf("************ %s(%d) listen_sock:%d\n", __func__, __LINE__, listen_sock);
    close(listen_sock);
    TcpServerHandle = NULL;
    vTaskDelete(NULL);
        printf("************ %s(%d) listen_sock:%d\n", __func__, __LINE__, listen_sock);
}

void tcpServeTaskStartUp(void)
{
    tcpServeTaskStop();
    xTaskCreate(tcpServeTask, "TCP_CLIENT_TASK", 8192, (void*)AF_INET, 5, &TcpServerHandle);
}

void tcpServeTaskStop(void)
{
    if (TcpServerHandle != NULL)
    {
        vTaskDelete(TcpServerHandle);
        TcpServerHandle = NULL;
    }
    if (listen_sock > 0)
    {
        printf("************ %s(%d) listen_sock:%d\n", __func__, __LINE__, listen_sock);
        close(listen_sock);
        printf("************ %s(%d) listen_sock:%d\n", __func__, __LINE__, listen_sock);
        listen_sock = 0;
    }
}

通过打印,发现socket没有释放,于是menuconfig TCP参数,减小MSL时间,将socket数量提高到16,但依然会出现无法分配socket问题

Code: Select all

(16) Maximum active TCP Connections
(16) Maximum listening TCP Connections
[*] TCP high speed retransmissions
(12) Maximum number of retransmissions of data segments
(12) Maximum number of retransmissions of SYN segments
(1440) Maximum Segment Size (MSS)
(250) TCP timer interval(ms)
(6000) Maximum segment lifetime (MSL)
(2000) Maximum FIN segment lifetime
(5744) Default send buffer size
(5744) Default receive window size
(6) Default TCP receive mail box size
[*] Queue incoming out-of-order segments
[ ]     Support sending selective acknowledgements
    Pre-allocate transmit PBUF size (MSS)  --->
(1500) Default TCP rto time
问题描述较长,麻烦好心人提供帮助,谢谢!

Who is online

Users browsing this forum: Google [Bot] and 182 guests