socket编程-recv()函数
问题描述:
我在非阻塞套接字(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错误可言!!) 为什么?
答
我的猜测是,你正在将O_NONBLOCK
调用放入你用于listen
的套接字中。但是一旦您拨打accept
,您将获得另一个代表连接的套接字。根据平台的不同,这个新的套接字可能会也可能不具有从另一个套接字继承的O_NONBLOCK。
引用我的Linux的man accept
:
在Linux上,通过
accept()
返回不继承文件状态标志,如从监听套接字O_NONBLOCK
和O_ASYNC
新的插座。这种行为不同于规范的BSD套接字实现。便携式程序不应该依赖来继承或不传递文件状态标志,并且总是明确地设置从accept()
返回的套接字上的所有必需标志。
在这里使用UDP套接字 – hroptatyr 2012-03-16 10:14:31