не удается подключиться к привязанному адресу сокета lwip после простоя в течение некоторого времени

Я использую lwIP под FreeRTOS, IP-сервер работает на устройстве на базе ARM (Xilinx Zynq-7020), а клиент - это Windows.

На стороне сервера, когда я привязываю, слушаю и принимаю адрес: порт, клиент может подключаться и читать / писать с этого адреса. И после выхода из программы, простоя в течение короткого времени (10 ~ 30 секунд), затем запускается снова, он также может читать / писать с сервера. Однако, когда я выхожу из клиента и долгое время простаиваю (> 30 с), я больше не могу подключиться к серверу. А на стороне сервера он больше не принимает адреса. Какие-нибудь решения?

Код для серверной части приведен ниже:

void echo_server( void *pvParameters )
{

    long lSocket, lClientFd, lAddrLen = sizeof( struct sockaddr_in );
    struct sockaddr_in sLocalAddr;
    struct sockaddr_in client_addr;

    static char dIn[BUF_SIZE];
    int ret;
    ( void ) pvParameters;

    int on = 1;
    int idle = 60;
    int intvl = 15;
    int cnt = 3;

    /* step 1. create and setopts */
    lSocket = lwip_socket(AF_INET, SOCK_STREAM, 0);

    if( lSocket >= 0 )
    {
        lwip_setsockopt(lSocket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
        //lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
        //lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
        //lwip_setsockopt(lSocket, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));

        memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));

        // prepare bind on port
        sLocalAddr.sin_family = AF_INET;
        sLocalAddr.sin_len = sizeof(sLocalAddr);
        sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        sLocalAddr.sin_port = ntohs( ( ( unsigned short ) ECHO_PORT ) );

        /* step 2. bind */
        if( lwip_bind( lSocket, ( struct sockaddr *) &sLocalAddr, sizeof( sLocalAddr ) ) < 0 )
        {
            lwip_close( lSocket );
            vTaskDelete( NULL );
        }

        /* step 3. listen */
        if( lwip_listen( lSocket, BACKLOG ) != 0 )
        {
            lwip_close( lSocket );
            vTaskDelete( NULL );
        }

        for( ;; )
        {

            /* step 4. accept */
            xil_printf("(ZYNQ-ECH) wait connection\n");
            lClientFd = lwip_accept(lSocket, ( struct sockaddr * ) &client_addr, ( u32_t * ) &lAddrLen );
            xil_printf("(ZYNQ-ECH) accept connection\n");

            lwip_setsockopt(lClientFd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
            //lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
            //lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl));
            //lwip_setsockopt(lClientFd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));

            // if client socket created
            if( lClientFd > 0L )
            {

                int packet = 0;
                while(1)
                {

                    ret = mfeit_read(lClientFd, dIn);
                    if (ret == -1 || ret == 0)
                        break;

                    ret = mfeit_write( lClientFd, dIn, ret );
                    if (ret == -1 || ret == 0)
                        break;

                    packet ++;

                }
                xil_printf("(ZYNQ-ECH) close connection, total = %d\n", packet);
                lwip_close( lClientFd );
            }
        }
    }

    /* Will only get here if a listening socket could not be created. */
    xil_printf("(ZYNQ-ECH) task killed !!\n");
    vTaskDelete( NULL );
}

person liubenyuan    schedule 07.02.2015    source источник


Ответы (1)


Я забыл об этом, но сначала вам нужно настроить правильный способ сохранения активности.

  1. настроен keep-alive на сервере, поэтому, как долго он сохраняет активность

  2. установите подходящее время для сохранения активности на вашей стороне.

  3. Не делайте keep-alive 2 часа или около того. Создайте новый сокет, потому что это плохо для ресурсов сервера.

person Danijel    schedule 22.03.2015
comment
Привет, я пробовал сохранить активность с помощью разных опций, например int on = 1; unsigned int idle = 7200; // in seconds unsigned int intvl = 3600; // in seconds unsigned int cnt = 9; lwip_setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); lwip_setsockopt(socket, SOL_SOCKET, TCP_KEEPIDLE, (void *)&idle, sizeof(idle)); lwip_setsockopt(socket, SOL_SOCKET, TCP_KEEPINTVL, (void *)&intvl, sizeof(intvl)); lwip_setsockopt(socket, SOL_SOCKET, TCP_KEEPCNT, (void *)&cnt, sizeof(cnt));, все они не работают. Я погуглил и обнаружил, что MAC-адрес может быть проблемой, когда я устанавливаю MAC вручную. - person liubenyuan; 23.03.2015
comment
(продолжение) MAC-адрес 00-13-14-15-15-16 и маршрутизация приложения lwip через маршрутизатор на ПК, может ли это быть проблемой? - person liubenyuan; 23.03.2015
comment
Хм, MAC может быть проблемой, но проверяли ли вы, что происходит в сети через WireShark (wirehark.org/ download.html) что ли? Подключите его прямо к локальной сети вашего ПК и посмотрите, что происходит. Пакеты KEEP_ALIVE должны быть отправлены, если это не проблема на устройстве, если они отправлены, то сервер не принимает keep-alive (я думаю, что это должно быть настроено, не уверен). - person Danijel; 23.03.2015