Switching between statements if the user inputs something: infinitely and with a timeout [duplicate]

那年仲夏 提交于 2019-12-11 14:13:28

问题


To explain more clearly what I want to do, I want my code to check if the user inputs something (or if another file descriptor than 0 has data to read) every (let's say) 2.5 seconds and so until the program stops.

If the user inputs something, a simple printf() will notify him and then the program will check again if the user inputs something in the next 2,5 seconds.

Else, it should simply print that the time ran out and then check again for the user input in the next 2,5 seconds.

And here's the code snippet I stole from Beej's Guide to Network Programming and modified to (try to) fulfill my requirements:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define STDIN 0  // file descriptor for standard input

int main(void){
    struct timeval tv;
    fd_set readfds;

    FD_ZERO(&readfds);
    FD_SET(STDIN, &readfds);

    tv.tv_sec = 2;
    tv.tv_usec = 500000;

    while(1){
        select(STDIN+1, &readfds, NULL, NULL, &tv);

        if (FD_ISSET(STDIN, &readfds)){
            printf("A key was pressed!\n");
            tv.tv_sec = 2;
            tv.tv_usec = 500000;

        }else{
            printf("Timed out.\n");
            tv.tv_sec = 2;
            tv.tv_usec = 500000;

        }

    }
    return 0;
}

As long I don't press any key, this works fine and prints "Timed out." every 2,5 seconds. But if I enter something, it seems to ignore the user input and keeps printing "Timed out.".

On the other hand, if I declare the fd_set and the struct timeval inside the infinite loop, once I enter something, this prints infinitely that a key has been pressed as if it ignores the timeout.

I have no idea why such a simple code doesn't work. I guess I'm missing some point about file descriptors I don't know about.


回答1:


Because you should reset -> FD_ZERO(&readfds) your readfds and add the file desciptor -> FD_SET(STDIN, &readfds) every time select returns, since on timeout the file descriptor is removed from the set

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define STDIN 0  // file descriptor for standard input

int main(void){
    struct timeval tv;
    fd_set readfds;

    while (1) {
        int count; /* how many descriptors are contained in the set. */

        FD_ZERO(&readfds);
        FD_SET(STDIN, &readfds);

        tv.tv_sec = 2;
        tv.tv_usec = 500000;

        count = select(STDIN + 1, &readfds, NULL, NULL, &tv);
        if ((count > 0) && (FD_ISSET(STDIN, &readfds) != 0)) {
            printf("A key was pressed!\n");
        } else if (count == -1)
            /* check for the error here */
        } else {
            printf("Timed out.\n");
        }
    }
    return 0;
}

as you see you should also check the return value from select, to check for an error, in case of an error, then check errno to see what happened, and then you check it the file descritor you're interested in is contained in readfds.



来源:https://stackoverflow.com/questions/27623603/switching-between-statements-if-the-user-inputs-something-infinitely-and-with-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!