1

在以下代码中使用计时器时,要么"Error calling select"出现错误,要么出现新数据:

    timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    if( select(s + 1, &readmask, NULL, NULL, &tv ) <= 0 )
    {
         perror("Error calling select");
         return 0;
    }

为了避免在重新访问此代码时出现此错误,可以在客户端执行哪些操作而不中断会话?

4

1 回答 1

2

您不应将其<= 0用作条件,因为0这意味着超时并< 0意味着错误。

选择:

if(int rv = select(s + 1, &readmask, NULL, NULL, &tv ); rv > 0) {
    // success
} else if(rv == 0) {
    // timeout
} else {
    // error
}

为了避免在重新访问此代码时出现此错误,可以在客户端执行哪些操作而不中断会话?

如果在将代码更改为上述代码后超时太快,则应仔细查看timeout参数。您应该在每次调用之前重新初始化它select

"在 Linux 上,select()修改timeout以反映不睡觉的时间量;大多数其他实现不这样做。(POSIX.1允许任何一种行为。)当读取timeout的 Linux 代码移植到其他操作系统时,以及将代码移植到其他操作系统时,这都会导致问题Linux 在循环中重用一个struct timevalfor 多个select()s 而不重新初始化它。考虑超时在select()返回后未定义。

...

"在 Linux 上,select()还修改timeout调用是否被信号处理程序中断(即EINTR错误返回)。这是不允许的POSIX.1 "

于 2020-01-19T12:56:27.643 回答