2012-03-16 44 views
0

我在非阻塞套接字(unix下的c语言)中有recv()函数的问题 我已经设置套接字为非阻塞下面的代码(服务器程序):socket编程-recv()函数

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错误可言!!) 为什么?

+0

在这里使用UDP套接字 – hroptatyr 2012-03-16 10:14:31

回答

3

我的猜测是,你正在将O_NONBLOCK调用放入你用于listen的套接字中。但是一旦您拨打accept,您将获得另一个代表连接的套接字。根据平台的不同,这个新的套接字可能会也可能不具有从另一个套接字继承的O_NONBLOCK。

引用我的Linux的man accept

在Linux上,通过accept()返回不继承文件状态标志,如从监听套接字O_NONBLOCKO_ASYNC新的插座。这种行为不同于规范的BSD套接字实现。便携式程序不应该依赖来继承或不传递文件状态标志,并且总是明确地设置从accept()返回的套接字上的所有必需标志

+0

thanks.so你的意思是我必须调用fcntl()的每个套接字返回接受? – Mushtu 2012-03-16 10:27:06

+0

是的,就是这样。或者如果你使用的是linux,你可以调用GNU特有的'accept4()'函数,它接收一个额外的参数并为你做。 – rodrigo 2012-03-16 10:30:29

+0

你的猜测是正确的。我打电话fcntl()为每个连接和它的作品。感谢这么多 – Mushtu 2012-03-16 10:36:56