C套接字中的非阻塞recv()

时间:2013-05-15 12:18:24

标签: c sockets send nonblocking recv

我在套接字中使用无限循环,如果它接收到一些数据,它应该接收它,或者它是否想要发送它发送的数据。下面给出的东西。我正在使用选择。我只有一个插座sd。

fd_set readsd;
int maxsd = readsd +1;
// all those actions of setting maxsd to the maximum fd +1 and FDSETing the FDs.
while(1)
{
     FD_ZERO(&read_sd);
     FD_SET(sd, &read_sd);
     if(FD_ISSET(sd, &readsd))
     {
       //recv call
     }
     else
     {
       //send call
     }
}

据我所知,select先选择一个数据到达的套接字描述符。但是这里我只有一个套接字,如果有一些数据我想恢复,或者我想发送其他信息。

在这种情况下,上面给出的代码是否合适?或者我还有其他一些我不知道的选择?

4 个答案:

答案 0 :(得分:3)

  

在这种情况下,上面给出的代码是否正常?

我没有看到任何选择的电话。此外,如果“maxsd”被设计为select的第一个参数,则其值是错误的:它必须是bigest文件描述符+1。无论如何,您只需使用标志MSG_DONTWAIT调用recv,在这种情况下,如果没有要读取的数据,它将返回错误。

答案 1 :(得分:2)

这有点依赖......首先,你真的在真实代码中有select个电话?

现在关于阻止...如果select返回你的套接字设置在读取集中,那么你可以保证你可以不阻塞地调用recv。但是无法保证可用的数据量。如果您使用UDP,那么将至少有一个(希望是完整的)数据包,但如果您使用TCP,则可能只获得一个字节。对于某些带有邮件边界的协议,您可能无法获得完整邮件,并且您必须在循环中调用recv才能获取所有邮件,不幸的是,这迟早会导致recv调用块。

简而言之,使用select会有所帮助,但在所有情况下都无济于事。实际保证recv调用不会阻塞的唯一方法是使套接字不阻塞。

答案 2 :(得分:1)

我不太确定你要做什么,所以我可以考虑两个选择:

将套接字设置为非阻止

由于您似乎只有一个套接字,因此您可以使用fcntl将套接字设置为非阻止模式并调用recv()

fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
// if fcntl returns no error, sock is now non-blocking

设置选择计时器

使用select你可以设置一个计时器,在一段时间后发生强制返回,即使没有收到任何数据。

答案 3 :(得分:0)

首先,我在您的代码中找不到任何select

但是,您可以先致电fcntl(fd, F_SETFL, flags | O_NONBLOCK)以使您的套接字无阻塞。如果您无法从errno == EWOULDBLOCK读取任何内容,请检查recv是否有效。在这种情况下,您无需使用select