簡體   English   中英

如何使read()成為非阻塞狀態並重置read()

[英]How to make read() non-blocking and reset read()

所以我做了一個像倒計時的功能。我想在倒數減少的同時讀取命令。 我的大問題是要使read()在倒數遞減時等待輸入。如您所見,我嘗試使用select()但在第一個printf("timeout.\\n"); 它停止嘗試閱讀。 我僅使節目timeout一次,否則它將一直持續到倒數計時達到0為止。我需要再次嘗試閱讀。

int timer(int seconds) 
{
    time_t start, end;
    double elapsed;
    int opened=0; 
    char command[10];
    struct timeval tv;
    int fd_stdin,rv;
    fd_set rd;

    fd_stdin=fileno(stdin);

    FD_ZERO(&rd);
    FD_SET(fileno(stdin),&rd);

    tv.tv_sec=5;
    tv.tv_usec=0;

    time(&start);  /* start the timer */

    do
    {
        time(&end);

        elapsed = difftime(end, start);

        if(fmod(elapsed,5)==0)
        {
            printf("Time remaining: %f minutes.\n", (seconds-elapsed)/60);
            sleep(1);
            if(opened==0)
            {
                printf("Use opentest to open your test.\n");
                opened=1;
            }
            fflush(stdout);
        }
        int c;
        rv=select(fd_stdin+1,&rd,NULL,NULL,&tv);
        if(rv==-1)
        {
            perror("Error on select.\n");
            exit(1);
        }
        else if (rv==0 && c!=1)
        {
            printf("timeout.\n");
            rv=select(fd_stdin+1,&rd,NULL,NULL,&tv);
            c=1;
        }
        else 
        {
            c=0;
            read(fd_stdin,command,10);
        }
    }
    while(elapsed < seconds);
    return 0;
}

編輯:要使用fmod()函數,我將這樣編譯: gcc client.c -lm -o client.exe 我不認為這是問題所在,但我不確定。

select()在退出時修改fd_set ,以反映已發送信號的描述符。 您不會在每次超時后重置fd_set

同樣,在某些平台上, select()修改timeval結構以反映剩余時間,因此,每次在這些平台上調用select() ,都必須重置timeval

同樣,您的c變量在循環內聲明,並且未初始化。 而是將其移到循環之外。

嘗試更多類似這樣的方法:

int timer(int seconds) 
{
    time_t start, end;
    double elapsed;
    int opened = 0; 
    char command[10];
    struct timeval tv;
    int fd_stdin, rv;
    fd_set rd;
    int c = 0;

    fd_stdin = fileno(stdin);

    time(&start);  /* start the timer */

    do
    {
        time(&end);

        elapsed = difftime(end, start);

        if (fmod(elapsed, 5) == 0)
        {
            printf("Time remaining: %f minutes.\n", (seconds-elapsed)/60);
            sleep(1);
            if (opened == 0)
            {
                printf("Use opentest to open your test.\n");
                opened = 1;
            }
            fflush(stdout);
        }

        FD_ZERO(&rd);
        FD_SET(fd_stdin, &rd);

        tv.tv_sec = 5;
        tv.tv_usec = 0;

        rv = select(fd_stdin+1, &rd, NULL, NULL, &tv);
        if (rv == -1)
        {
            perror("Error on select.\n");
            exit(1);
        }
        else if (rv == 0)
        {
            if (c != 1)
            {
                printf("timeout.\n");
                c = 1;
            }
        }
        else 
        {
            c = 0;
            read(fd_stdin, command, 10);
        }
    }
    while (elapsed < seconds);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM