日期:2014-05-16  浏览次数:20832 次

select立刻返回0,errno=0,根本没有等到超时的情况,为何
...
tv.tv_sec   =   timeout;

for(   ;;   )
{
        FD_ZERO(   &readmask   );
        FD_SET(   sockfd,   &readmask   );

        switch(   select(   sockfd   +   1,   &readmask,   NULL,   NULL,   &tv   )   )
        {
        case   0:
                  return   TIMEOUT;
        case   -1:
                  if   (   errno   ==   EINTR   )
                            continue;
                  return   BROKEN;
        default:
                  if   (   FD_ISSET(   sockfd,   &readmask   )   )
                  {
                        ...
                  }
        }
}
...

奇怪的是,明明timeout> 0,但是select立刻返回0,实际上客户端发送报文是成功的,而服务端却收不到数据(TIMEOUT)。

sockfd是子进程通过recvmsg从父进程接收过来的,父进程那边accept后就用sendmsg发给子进程了,中间没有做其他操作。

本来程序一直正常的,但是最近偶然就会出现这种情况,而且有时几个子进程,有的正常,有的就有这种情况。

各位高手能否指点一下,为什么会出现这种情况?


------解决方案--------------------
tv.tv_sec = timeout;
这条语句要在select之前,循环之内。
------解决方案--------------------
tv.tv_sec = timeout;
这条语句要在select之前,循环之内。
——————————————————————————
这句话没有必要吧,只读的

——————————————————————————

struct timeval
{
time_t tv_sec;
time_t tv_usec;
};
是不是搂主设的是tv_usec太小了阿,有的系统达不到你设的这个精度就会出现你说的问题

------解决方案--------------------
tv.tv_sec = timeout;
这条语句要在select之前,循环之内。
——————————————————————————
这句话没有必要吧,只读的

——————————————————————————

struct timeval
{
time_t tv_sec;
time_t tv_usec;
};
是不是搂主设的是tv_usec太小了阿,有的系统达不到你设的这个精度就会出现你说的问题
-----------
rexp(沧浪客) 说得很好!

man select
...
....
BUGS
Version 2 of the Single UNIX Specification (``SUSv2 ' ') allows systems to
modify the original timeout in place. Thus, it is unwise to assume that
the timeout value will be unmodified by the select() system call.

------解决方案--------------------
tv.tv_sec = timeout;
这条语句要在select之前,循环之内。
——————————————————————————
这句话没有必要吧,只读的

——————————————————————————

完全要这样做,因为tv 会被改写成 rest 时间,大部分情况是 0
------解决方案--------------------
每次select 之前,设置tv.tv_sec这个时间,应该就可以了。
------解决方案--------------------
tv.tv_sec = 5
tv.tv_usec = 0;//add

try it again