2012-03-16 5 views
0

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

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

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

i sued функция выбора в моем коде тоже.

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 вообще !!) Почему?

+0

работает здесь с гнездом UDP – hroptatyr

ответ

3

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

Цитируя man accept из моего Linux:

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

+0

thanks.so вы имеете в виду, что я должен вызывать fcntl() для каждого сокета, возвращаемого accept? – Mushtu

+0

Да, именно это. Или, если вы используете linux, вы можете вызвать функцию 'accept4()' GNU, которая получает дополнительный параметр и делает это для вас. – rodrigo

+0

Ваша догадка была правильной. Вызов fcntl() для каждого соединения и его работ. Большое спасибо – Mushtu