fd_set rset;
struct timeval tv;
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
tv.tv_sec = 1;
tv.tv_usec = 0;
for(;;)
{
for(count = 0; count < elements in sockaddr_in array; count++)
{
//flag_array is filled with -1 before for(;;)
if(flag_array[count] == -1 && select(sockfd+1, &rset, NULL, NULL, &tv))
{
recvfrom(...)
}
tv.tv_sec = 1;
FD_ZERO(&rset);//this fixed it
FD_SET(sockfd, &rset);//and this too
}
//contact everyone from sockaddr array (works like a charm!)
}
如果我没有在"超时"发生之前将消息从其他程序发送到此程序,则select语句"失败",因此我不能在其中使用recvfrom语句。我曾经这样做过,使我的另一个程序在无限循环中与这个程序接触,它永远不会进入if语句。
什么是有效的:如果我在每次超时发生之前联系这个程序,一切都很好。如果我把recvfrom语句放在If语句之外(___ &&选择),它工作完全正常。
这里有一个小图表,这个程序将被称为Recv:
if(A contacts Recv before timeout) count = 0
Recv stores contact A in struct
if(B contacts Recv before timeout) count = 1
Recv stores contact B in struct
if(timeout) count = 2
if(C contacts Recv after timeout) count = 3
nothing
count = 4
程序会很好地联系A和B//返回到循环开始
flag_array == -1 is false count = 0
flag_array == -1 is false count = 1
flag_array == -1 is true...select "fails" count = 2..3..4..(exit loop)
在发布这篇文章前2分钟,我决定最后看一下我以前的代码。我想我忘了
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
在for循环之后(其中tv。Tv_sec = 1) is at.
谁能详细说明一下为什么有必要这样做?select()
修改传递的fd_set
-您必须在每次调用select()
之前设置它。这就是select()
应该如何工作。
这是必要的,因为select()
可能会修改文件描述符集。
引用自Linux手册中的select(3):
成功完成后,pselect()或select()函数将修改readfds、writefds和errorfds参数所指向的对象,分别指示哪些文件描述符已准备好可读、准备好可写或等待错误条件,并返回所有输出集中已准备好的描述符的总数。对于每个小于nfds的文件描述符,如果在输入时设置了相应的位,并且该文件描述符的相关条件为真,则在成功完成时设置相应的位。
注意select()
也可以修改它的struct timeval
参数,例如Linux将经过的时间存储在其中。因此,您应该重置tv
的所有字段。