select 和 receivefrom 出现意外结果
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(___ && select) 之外,它就完全可以正常工作。
这是一个小图,该程序将被称为 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 //在发布此内容之前 2 分钟回到循环开始
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)
我决定最后看一下我以前的代码。我想我
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
在 for 循环(其中 tv.tv_sec = 1)之后忘记了。
有人可以详细说明为什么有必要这样做吗?
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!)
}
If I don't send my message from my other program to this program before a "timeout" occurs, the select statement "fails", so I can't use the recvfrom statement inside of it. I once made it so that my other program contacts this one on an infinite loop, it never went inside of the if statement.
What does work:
If I contact this program before each timeout occurs, everything is fine.
If I put the recvfrom statement outside of the if(___ && select), it works completely fine.
Here's a little diagram where this program is going to be called 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
the program will contact A and B just fine
//goes back to start of loop
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 minutes before posting this I decided to take one last look at my previous code. I guess I forgot
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
after the for loop (where tv.tv_sec = 1) is at.
Can someone elaborate on why it's necessary to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
select()
修改传递的fd_set
- 您必须在每次调用select()
之前对其进行设置。这就是select()
应该如何工作的。select()
modifies the passedfd_set
- You have to set it up before each call toselect()
. This is just howselect()
should work.这是必要的,因为
select()
可能会修改文件描述符集。引用 select(3) 的 Linux 手册页:
请注意,
select()
还可以修改其struct timeval
参数,例如Linux 在其中存储经过的时间。因此,您还应该重置tv
的所有字段。It's necessary because
select()
may modify the file descriptor sets.Citing from the Linux manpage for select(3):
Note that
select()
may also modify itsstruct timeval
argument, e.g. Linux stores the elapsed time in it. Thus, you should reset all fields oftv
as well.