2

大多数情况下,这段代码工作得很好。但有时当可执行文件运行了一段时间后,select() 似乎立即超时,然后进入一个奇怪的状态,它不断被调用,立即超时,一遍又一遍。然后必须从外面杀死它。

我的猜测是标准输入超时更改的方式是错误的——这就是 select 阻塞的原因。

在 StackOverflow 上环顾四周,大多数人的 select() 问题似乎都可以通过确保每次都使用宏(FD_ZERO 和 FD_SET)重置并使用正确的初始参数进行选择来解决。我不认为这些是这里的问题。

int            rc     = 0;
fd_set         fdset;
struct timeval timeout;

// -- clear out the response -- //
readValue = "";

// -- set the timeout -- //
timeout.tv_sec = passedInTimeout;  // 5 seconds
timeout.tv_usec = 0;

// -- indicate which file descriptors to select from -- //
FD_ZERO(&fdset);
FD_SET(passedInFileDescriptor, &fdset); //passedInFileDescriptor = 0

// -- perform the selection operation, with timeout -- //
rc = select(1, &fdset, NULL, NULL, &timeout);


if (rc == -1)  // -- select failed -- //
{
    result = TR_ERROR;
}
else if (rc == 0)  // -- select timed out -- //
{
    result = TR_TIMEDOUT;
}
else 
{
    if (FD_ISSET(mFileDescriptor, &fdset))
    {
        if(rc = readData(readValue) <= 0)
        {
            result = TR_ERROR;
        }
    } else {
       result = TR_SUCCESS;
    }
}
4

4 回答 4

1

我遇到了同样的问题,它在 Windows 上运行良好,但在 linux 上运行良好,并且我将 maxfd 设置为最后一个套接字 + 1。它在长时间运行后会定期发生。我在接受时拿起连接,然后第一次调用 select 定期超时。

于 2011-05-11T17:10:56.510 回答
1

请注意,“select”的某些实现严格应用规范:“nfds 是三个集合中任何一个中编号最高的文件描述符,加 1”。因此,您最好将“1”更改为“passedInFileDescriptor+1”作为第一个参数。我不知道这是否可以解决您的问题,但至少您的代码变得更加……嗯……“传统”;)

再见

于 2011-04-01T21:06:28.057 回答
1

在某些操作系统上,timeout调用时会修改select以反映未睡觉的时间量。在您的示例中看起来您并没有重复使用timeout,但请确保您确实在每次调用之前将其重新初始化为 5 秒select

于 2011-04-01T23:24:55.300 回答
0

看看这段代码:

if (FD_ISSET(mFileDescriptor, &fdset))
{
    if(rc = readData(readValue) <= 0)
    {
        result = TR_ERROR;
    }
} else { 
   result = TR_SUCCESS;
}

这里有两件事困扰着我:

  1. 如果您的 FD 中没有数据(例如发生错误),FD_ISSET() 将返回false并且您的函数返回 TR_SUCCESS!?
  2. FD_SET(passedInFileDescriptor, &fdset),但检查另一个值:FD_ISSET(mFileDescriptor, &fdset)。如果mFileDescriptor !=passedInFileDescriptor在某个时候,你会落入我的第一个假设。

它应该看起来像这样:

if (FD_ISSET(passedInFileDescriptor, &fdset))
{
    if(rc = readData(readValue) <= 0)
    {
        result = TR_ERROR;
    }
    else 
    {
        result = TR_SUCCESS;
    }
}
else
{
    result = TR_ERROR;
}

不?

(编辑:另外,这个答案也指出了您使用select()错误的high_fd值的问题)

另一个编辑:好吧,看起来这些家伙再也没有回来......令人沮丧。

于 2011-08-17T14:12:29.603 回答