0

我在套接字中使用无限循环,如果它接收到一些数据,它应该接收它,或者它想要发送它发送的数据。如下所示。我正在使用选择。我只有一个socket 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 选择数据首先到达的套接字描述符之一。但是这里我只有一个套接字,如果有数据我想recv,否则我想发送。

在那种情况下,上面给出的代码可以吗?或者还有其他我不知道的选择?

4

4 回答 4

3

在那种情况下,上面给出的代码可以吗?

我没有看到任何要求选择的电话。另外,如果“maxsd”被设计为select的第一个参数,它的值是错误的:它必须是最大的文件描述符+1。无论如何,您可以简单地调用带有标志 MSG_DONTWAIT 的 recv,在这种情况下,如果没有要读取的数据,它将返回错误。

于 2013-05-15T12:32:01.193 回答
2

这取决于...首先,您实际上确实select在您的真实代码中有一个调用?

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

简而言之,使用select有帮助,但并非在所有情况下都有帮助。真正保证recv调用不会阻塞的唯一方法是使套接字成为非阻塞的。

于 2013-05-15T12:27:53.430 回答
2

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

将套接字设置为非阻塞

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

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

设置选择计时器

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

于 2013-05-15T12:35:10.953 回答
0

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

但是,您可以fcntl(fd, F_SETFL, flags | O_NONBLOCK)先调用以使您的套接字非阻塞。然后检查errno == EWOULDBLOCK您是否无法从recv. select在这种情况下你不需要使用。

于 2013-05-15T12:37:08.523 回答