функция программирования сокетов recv () - PullRequest
0 голосов
/ 16 марта 2012

У меня проблема с функцией recv () в неблокирующем сокете (язык c под unix). Я установил неблокируемый сокет с кодом ниже (серверная программа):

int x;
x=fcntl(listen_sd,F_GETFL,0);
fcntl(listen_sd,F_SETFL,x | O_NONBLOCK);

когдая вызываю recv(), если сообщение доступно, оно возвращает длину сообщения, если нет, оно блокируется !!

Я также подал в суд на функцию выбора.

while(1)
       {
          /**********************************************/
          /* Receive data on this connection until the  */
          /* recv fails with EWOULDBLOCK.  If any other */
          /* failure occurs, we will close the          */
          /* connection.                                */
          /**********************************************/
          rc = recv(i, buffer, sizeof(buffer), 0);
          if (rc < 0)
          {
         if(errno == EAGAIN||errno == EWOULDBLOCK)
         {
        printf("no message\n");
        break;
         }

                perror(" recv() failed");
                close_conn = TRUE;

          }

          /**********************************************/
          /* Check to see if the connection has been    */
          /* closed by the client                       */
          /**********************************************/
          if (rc == 0)
          {
             printf("connection closed\n");
             close_conn = TRUE;
             break;


          }

          /**********************************************/
          /* Data was recevied                          */
          /**********************************************/
          len = rc;
          printf("  %d bytes received\n", len);
        }

если клиент отправилсообщение и не закрывает соединение, тогда сервер при первом вызове recv () получает сообщение, а при втором вызове блокируется (другими словами, recv () вообще не возвращает ошибку EWOULDBLOCK !!) Почему?

1 Ответ

3 голосов
/ 16 марта 2012

Я предполагаю, что вы помещаете вызов O_NONBLOCK в сокет, который вы используете для listen.Но как только вы позвоните accept, вы получите другой сокет, представляющий соединение.Этот новый сокет может иметь или не иметь O_NONBLOCK, унаследованный от другого, в зависимости от платформы.

Цитирование man accept из моего linux:

В Linux новыйСокет, возвращаемый accept(), не наследует флаги состояния файла, такие как O_NONBLOCK и O_ASYNC, от прослушивающего сокета.Это поведение отличается от реализации канонических сокетов BSD.Переносимые программы не должны полагаться на наследование или отсутствие наследования флагов состояния файла, а всегда явно устанавливает все необходимые флаги в сокете, возвращаемом из accept().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...