esp32 idf多路服务器

时间:2018-07-11 10:51:39

标签: c sockets server esp32

这是我的第一篇文章,因此远程询问是否有帮助,而我没有提供。

我的应用程序要求同时从主服务器打开多个套接字,然后从属服务器连接到WiFi,然后再连接到套接字

问题是:我必须使它“防弹”,以防止不断不断地从奴隶重新连接,并且我收到Accept错误: E(23817)TCP套接字:接受错误:-1系统中打开的文件过多 当我第五次重新连接客户端时,当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()过程来正确关闭Task,以正确关闭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]));
            }
        }       
    }
}

2 个答案:

答案 0 :(得分:1)

我在任何地方都看不到您关闭您的插座吗?

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

在不再需要连接时立即关闭

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

对于recv,还有一种特殊情况,即它返回零。这意味着另一端已关闭连接。当然,您还需要结束自己的工作。

答案 1 :(得分:0)

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