соединение с сокетом потеряно с помощью функции выбора

#sockets #select #server

#сокеты #выберите #сервер

Вопрос:

Я новичок в программе сокетов. Я создал свою серверную программу с хорошим образцом программы, используя функцию выбора.

Он хорошо работает примерно с 20 000 подключений. Но в некоторых случаях соединение принимает двойное следствие без получения данных из первого сокета. Только данные, полученные от второго сокет-соединения. После этого первый ресурс сокета не может быть освобожден. FD_SET и FD_ISSET не работают с первым сокетом, если следствие примет, я думаю.

Рабочих клиентов 6.

Перед этой ситуацией примите, получите данные и закройте сокет, примите, данные rcv, закройте…

В этом случае примите, примите, получите данные из второго сокета и закройте второй сокет. Потеряно первое соединение с сокетом.

После этого примите назначение функции второго дескриптора сокета.

В чем проблема? Как можно освободить сокет fisrt?

БР Пол

Комментарии:

1. Это явно связано с ошибкой в вашем коде, но мы ее не видим. Пожалуйста, покажите фактический код, с которым у вас возникли проблемы.

Ответ №1:

Мой код выглядит следующим образом:

 while(1) 
    {
    //clear the socket set
    FD_ZERO (amp;readfds);

    //add master socket to set
    FD_SET (sever_socket, amp;readfds);
    max_sd = sever_socket;

    //add child sockets to set
    for ( i = 0 ; i < MAX_CLIENT ; i   ) 
        {
        //socket descriptor
        sd = client_socket [i];

        //if valid socket descriptor then add to read list
        if (sd > 0)
            {
            FD_SET( sd , amp;readfds);
            }

        //highest file descriptor number, need it for the select function
        if(sd > max_sd)
            {
            max_sd = sd;
            }
        }
    
    //wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely
    activity = select ( max_sd   1 , amp;readfds , NULL , NULL , NULL);
    if ((activity < 0) amp;amp; (errno!=EINTR)) 
        {
        LOG_F (WARNING, "select error");
        }

    //If something happened on the master socket, then its an incoming connection
    if (FD_ISSET(sever_socket, amp;readfds)) 
        {
        if ((new_socket = accept (sever_socket, (struct sockaddr *) amp;address, (socklen_t*) amp;addrlen)) < 0)
            {
            perror("accept");
            exit(EXIT_FAILURE);
            }

        //inform user of socket number - used in send and receive commands
        LOG_F (INFO, "New connection, socket fd is %d, ip is : %s, port : %d", 
            new_socket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));

        //add new socket to array of sockets
        for (i = 0; i < MAX_CLIENT; i  ) 
            {           
            //if position is empty
            if( client_socket[i] == 0 )
                {
                client_socket[i] = new_socket;
                LOG_F (INFO, "Adding to list of sockets as %d" , i);
                break;
                }
            }
        }

    for (i = 0; i < MAX_CLIENT; i  ) 
        {
        sd = client_socket[i];
             
        if (FD_ISSET (sd , amp;readfds)) 
            {
            memset (amp;rcvBuf, 0x00, sizeof(rcvBuf));
            if ((fp = fdopen (sd, "r")) == NULL) 
                {
                LOG_F (WARNING, "TCP_SOCKET FD_OPEN Error");
                close (sd);
                client_socket[i] = 0;
                }
            else 
                {
                ret = ioctl (sd, FIONREAD, amp;nread);
                
                if (nread == 0) 
                    {
                    fclose (fp);
                    close (sd);
                    client_socket[i] = 0;
                    LOG_F (WARNING, "Client disconnected(as %d, fd %d)", i, sd);                        
                    }
                else 
                    {
                    len = recv (sd, rcvBuf, nread, 0);
                    if (len > 0) 
                        {
                        LOG_F (INFO, "RECV size %d" , len);
                        ...
                        do_msg_handler ()
                     }
                 }
               ...