【问题标题】:esp32 idf multi-socket-serveresp32 idf 多套接字服务器
【发布时间】:2018-12-19 09:14:15
【问题描述】:

这是我的第一篇文章,所以如果有帮助,请远程请求任何东西,但我没有提供。

我的应用程序需要从 Master 一次打开多个套接字,然后从机连接到 WiFi,然后再连接到套接字

问题是:我必须使其“防弹”,以防止不断地从从站重新连接,我收到 Accept 错误: E (23817) TCP SOCKET: 接受错误: -1 系统中打开的文件太多 它出现在我第 5 次重新连接客户端时,在 menuconfig 中打开的最大套接字数 = 5 时,

当客户端在 1 秒内没有发送任何内容时,我会断开客户端与服务器的连接 -> 然后我假设他们得到了 DC-d。 我用 close() 过程来做。

void closeOvertimedTask(void * ignore)
{
    while(1)
    {
        for(int i = 0; i < openedSockets;)
        {
            if(needsRestart[i] == 1)
            {
                ESP_LOGI("RESTARTING", " task#%d",i);
                //lwip_close_r(clientSock[i]);

                //closesocket(clientSock[i]);

                //ESP_LOGI("closing result", "%d", close(clientSock[i]));
                stopSocketHandler(i);
                needsRestart[i] = 0;
                //if(isSocketOpened[i])
                {

                }

                ESP_LOGI("close", "%d", lwip_close_r(clientSock[i]));
                isSocketOpened[i] = 0;

                xTaskCreate( handleNthSocket, "TCP_HANDLER", 10*1024, &(sockNums[i]) , tskIDLE_PRIORITY, &socketHandlerHandle[i]);
                configASSERT(socketHandlerHandle[i]);
                needsRestart[i] = 0;
            }

            if(isSocketOpened[i])
            {
                int diff = ((int)((uint64_t)esp_timer_get_time()) - lastWDT[i]) - 2*TCPWDT;

                if(diff > 0)
                {
                    if(isSocketOpened[i])
                    {
                        ESP_LOGI("I FOUND OUT HE DC-d","");
                        //closesocket(clientSock[i]);
                    }
                    ESP_LOGI("close", "%d", close(clientSock[i]));

                    stopSocketHandler(i);
                    isSocketOpened[i] = 0;

                    xTaskCreate( handleNthSocket, "TCP_HANDLER", 10*1024, &(sockNums[i]) , tskIDLE_PRIORITY, &socketHandlerHandle[i]);
                    configASSERT(socketHandlerHandle[i]);
                }
            }

        }
    }
}

对于每个套接字,我运行 1 个任务,该任务应该从该套接字接收并采取进一步行动。

对于所有这些,我有另一个任务检查消息上次到达的时间,并在超过时间(即 2 秒)时重新启动任务

我需要在最终版本中打开大约 16 个套接字,因此在 Slave 重新启动整个连接后,没有空间让仍然关闭的套接字

  1. 如何正确关闭任务并在其中运行 recv() 过程以正确关闭 Socket。
  2. 如果 WiFi 没有实现 STA DC-d,有没有办法从服务器端读取套接字已关闭
  3. 这是关于来自 tcp 堆栈的 TIME_WAIT 吗?

套接字读取代码:

void handleNthSocket(void * param) // 0 <= whichSocket < openedSockets 
{
    int whichSocket =  *((int *) param);

    ESP_LOGI("TCP SOCKET", "%s     #%d", getSpaces(whichSocket), whichSocket);
    struct sockaddr_in clientAddress;

    while (1) 
    {
        if(needsRestart [whichSocket] == 0)
        {
            socklen_t clientAddressLength = sizeof(clientAddress);
            clientSock[whichSocket] = accept(sock[whichSocket], (struct sockaddr *)&clientAddress, &clientAddressLength);
            if (clientSock[whichSocket] < 0) 
            {
                ESP_LOGE("TCP SOCKET", "accept error: %d %s", clientSock[whichSocket], strerror(errno));  //HERE IT FLIPS
                //E (232189) TCP SOCKET: accept error: -1 Too many open files in system

                isSocketOpened[whichSocket] = 0;
                needsRestart[whichSocket] = 1;
                continue;
            }
            //isSocketOpened[whichSocket] = 1;
            // We now have a new client ...

            int total = 1000;

            char dataNP[1000];
            char *data;
            data = &dataNP[0];

            for(int z = 0; z < total; z++)
            {
                dataNP[z] = 0;
            } 
            ESP_LOGI("TCP SOCKET", "%snew client",getSpaces(whichSocket));
            ESP_LOGI("          ", "%s#%d connected",getSpaces(whichSocket), whichSocket);
            lastWDT[whichSocket] = (uint64_t)esp_timer_get_time() + 1000000;
            isSocketOpened[whichSocket] = 1;
            // Loop reading data.


            while(isSocketOpened[whichSocket]) 
            {
                /*
                if (sizeRead < 0) 
                {
                    ESP_LOGE(tag, "recv: %d %s", sizeRead, strerror(errno));                
                    goto END;
                }

                if (sizeRead == 0) 
                {
                    break;
                }
                sizeUsed += sizeRead;
                */

                ssize_t sizeRead = recv(clientSock[whichSocket], data, total, 0);
                /*for (int k = 0; k < sizeRead; k++)
                {
                    if(*(data+k) == '\n')
                    {
                        ESP_LOGI("TCP DATA  ", "%sthere was enter", getSpaces(whichSocket));
                        //ESP_LOGI("TIME      ", "%d", (int)esp_timer_get_time());
                    }
                    //ESP_LOGI("last wdt", "%d", (int)lastWDT[whichSocket]);

                }*/


                lastWDT[whichSocket] = (uint64_t)esp_timer_get_time();
                int diff = ((int)((uint64_t)esp_timer_get_time()) - lastWDT[whichSocket]) - 2*TCPWDT;
                ESP_LOGI("last wdt", "%d, data = %s", (int)lastWDT[whichSocket], data);

                if(diff > 0)
                {
                    ESP_LOGI("last wdt", "too long - %d", diff);
                    isSocketOpened[whichSocket] = 0;
                }

                if (sizeRead < 0)
                {
                    isSocketOpened[whichSocket] = 0;
                }


                //TODO: all RX from slave routine
                for(int k = 0; k < sizeRead; k++)
                {
                    *(data+k) = 0;
                }



    //          ESP_LOGI("lol data", "clientSock[whichSocket]=%d, 
                /*if(sizeRead > -1)
                {
                    ESP_LOGI("TCP DATA: ", "%c", *(data + sizeRead-1));
                }
                else
                {
                    ESP_LOGI("TCP DC    ", "");
                    goto END;               
                }*/     



            }
            if(isSocketOpened[whichSocket])
            {
                ESP_LOGI("closing result", "%d", close(clientSock[whichSocket]));
            }
        }       
    }
}

【问题讨论】:

    标签: c sockets server esp32


    【解决方案1】:

    我没有看到你在任何地方关闭你的套接字?

    无论平台如何,套接字通常都是有限的资源,并且是可以重复使用的资源。如果您不关闭套接字,那么系统会认为您仍然在使用,并且不能将这些套接字重新用于新连接(在 POSIX 系统上,即使打开 文件 也会受到影响)。

    当不再需要它们时,立即关闭连接。

    通常这是通过检查 recvsend 返回的内容来完成的:如果它们返回的值小于零,则会发生错误,并且在大多数情况下这是不可恢复的错误,因此应关闭连接。即使是可恢复的错误,关闭连接让客户端重新连接也更容易。

    对于recv,也有返回零的特殊情况。这意味着另一端已关闭连接。当然,你也需要结束你的结局。

    【讨论】:

      【解决方案2】:

      这篇文章解决了我所有的问题 https://www.esp32.com/viewtopic.php?t=911

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-30
        • 1970-01-01
        • 2015-05-15
        • 2017-02-25
        • 1970-01-01
        相关资源
        最近更新 更多