【问题标题】:How to recall select after timeout in C?如何在C中超时后召回选择?
【发布时间】:2016-04-22 06:27:14
【问题描述】:

我使用 select 进行同步 I/O 多路复用。它将检查任何数据 1 秒。1 秒后如果没有数据将显示输出 (puts("Waited for 1 sec no data");) 然后它将检查再次用于数据。但这仅在第一次起作用,然后进入无限循环。 有没有其他解决方案。

//..............................
//.............................
//Creating listener socket and other sort of things
struct timeval tv;
        tv.tv_sec=1;
        tv.tv_usec=0;

    while(1)
    {
    FD_ZERO(master);


    FD_SET(listener,master);
    fdmax = listener;
    int retval=select(fdmax+1,master, NULL, NULL,&tv);
    printf("retval is %d\n",retval);

            if(retval == -1)
            {
                    perror("Server-select() error");
            }else if(retval)
            {
                    puts("Data available");
                    //If there is no data do some work and checkagain.

            }else
            {
                    puts("Waited for 1 sec no data"); 
                    //If there is no data do some work and checkagain.

            }
      }

【问题讨论】:

  • timeval 结构声明了超时。如果您想在 I/O 之间等待一秒钟,您应该按照@Pierre 的建议进行操作。
  • select() 超时后是否关闭套接字?
  • 彻底阅读select 的手册页。它有很多提示:在 select() 返回后考虑未定义超时。
  • 只需在“checkagain:”标记后加上tv initalization,请不要再使用goto
  • @Pierre 使用sleep 的目的是什么?这段代码已经做了正确的事情,除了被接受的答案纠正的错误。 sleep 只是增加了应用程序既不能工作无法响应 I/O 的无用时间。

标签: c


【解决方案1】:

来自man select

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

因此,就像master,您必须在每次调用select 之前设置tv

在我的代码中,我经常有这样的东西:

FD_ZERO(master);
FD_SET(listener,master);
fdmax = listener;

while (1)
{
    struct timeval tv = {1, 0};

    int retval=select(fdmax+1,master, NULL, NULL,&tv);
    printf("retval is %d\n",retval);

    if(retval == -1) {
        perror("Server-select() error");
        break; //  <-- notice the break here
    } else if(retval) {
        puts("Data available");
    } else {
        puts("Waited for 1 sec no data"); 
    }
}

【讨论】:

    【解决方案2】:

    除了Mathieu 的回答,似乎每次调用select FD_ZERO 之前都必须先调用清空可读文件句柄集,然后再调用FD_SET。

    无论是否有数据要读取,我都在努力选择()在达到超时后总是返回 0(我从键盘读取输入,我用“cat”命令检查了每次按键时都会发送数据) .

    代码应该是(归功于以前的答案):

    while (1)
    {
    
        struct timeval tv = {1, 0};
        FD_ZERO(master);
        FD_SET(listener,master);
        fdmax = listener;
    
        int retval=select(fdmax+1,master, NULL, NULL,&tv);
        printf("retval is %d\n",retval);
    
        if(retval == -1) {
            perror("Server-select() error");
            break; //  <-- notice the break here
        } else if(retval) {
            puts("Data available");
        } else {
            puts("Waited for 1 sec no data"); 
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-24
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 2020-07-08
      • 2016-10-08
      • 2020-09-23
      相关资源
      最近更新 更多