【问题标题】:Unexpected results with select and recvfromselect 和 recvfrom 的意外结果
【发布时间】:2011-08-07 12:34:09
【问题描述】:
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就好了 //回到循环开始

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)位于。

有人可以详细说明为什么需要这样做吗?

【问题讨论】:

    标签: c udp recv select-function


    【解决方案1】:

    select() 修改传递的fd_set - 您必须在每次调用select() 之前进行设置。这就是select() 的工作方式。

    【讨论】:

      【解决方案2】:

      这是必要的,因为select() 可能会修改文件描述符集。

      引用the Linux manpage for select(3):

      成功完成后,pselect() 或 select() 函数应修改 readfds、writefds 和 errorfds 参数指向的对象,以指示哪些文件描述符已准备好读取、准备写入或有错误条件待处理,分别返回所有输出集中就绪描述符的总数。对于小于 nfds 的每个文件描述符,如果在输入时设置相应位并且该文件描述符的关联条件为真,则应在成功完成时设置相应位。

      请注意,select() 也可以修改其 struct timeval 参数,例如Linux将经过的时间存储在其中。因此,您也应该重置tv 的所有字段。

      【讨论】:

      • 我发现struct timeval 需要在再次调用select() 之前重置,例如它是否在while 循环中。
      猜你喜欢
      • 1970-01-01
      • 2015-10-02
      • 2014-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多