我在非阻塞套接字(unix下的c语言)中遇到recv()函数的问题 我已使用以下代码(服务器程序)将套接字设置为非阻塞:
int x;
x=fcntl(listen_sd,F_GETFL,0);
fcntl(listen_sd,F_SETFL,x | O_NONBLOCK);
当我呼叫recv()
时,如果消息可用,则返回消息的长度,如果不是则阻止!!
我也在我的代码中起诉了select函数。
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 :(得分:3)
我的猜测是你将O_NONBLOCK
调用放入用于listen
的套接字中。但是一旦你调用了accept
,你就会得到代表连接的另一个套接字。这个新套接字可能有也可能没有从另一个套接字继承的O_NONBLOCK,具体取决于平台。
引用我的linux中的man accept
:
在Linux上,
accept()
返回的新套接字不会从侦听套接字继承文件状态标志,例如O_NONBLOCK
和O_ASYNC
。此行为与规范BSD套接字实现不同。便携式程序不应依赖继承或不继承文件状态标志,始终在accept()
返回的套接字上显式设置所有必需的标志。