长运行后,select()会立即超时(C ++)

时间:2011-04-01 19:36:14

标签: c sockets select-function

大多数情况下,这段代码运行得很好。但有时当可执行文件运行一段时间后,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 个答案:

答案 0 :(得分:1)

请注意,“select”的某些实现严格适用于规范: “nfds是三组中任何一组中编号最大的文件描述符,加1”。 所以,你最好用“passInFileDescriptor + 1”作为第一个参数来改变“1”。 我不知道这是否可以解决你的问题,但至少你的代码变得更加......呃...“传统的”;)

再见

答案 1 :(得分:1)

在某些操作系统上,调用timeout时会修改select以反映未睡眠的时间。在您的示例中,您似乎不再使用timeout,但请确保在调用select之前每次重新初始化为5秒。

答案 2 :(得分:1)

我遇到了同样的问题,它在Windows上运行正常但在linux上运行不正常,我将maxfd设置为最后一个套接字+ 1.它在长时间运行后会定期发生。我在接受时接听连接,然后第一次选择定期选择超时。

答案 3 :(得分: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!= passInFileDescriptor 在某些时候,你将落入我的第一个 假设。
  3. 应该是这样的:

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

    没有?

    (编辑:同样,this answer也指出了您使用 high_fd 值错误的select()的问题

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