我在套接字中使用无限循环,如果它接收到一些数据,它应该接收它,或者它是否想要发送它发送的数据。下面给出的东西。我正在使用选择。我只有一个插座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先选择一个数据到达的套接字描述符。但是这里我只有一个套接字,如果有一些数据我想恢复,或者我想发送其他信息。
在这种情况下,上面给出的代码是否合适?或者我还有其他一些我不知道的选择?
答案 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
。