GNU/Linux >> Linux Esercitazione >  >> Linux

Come implementare un timeout nella chiamata alla funzione di lettura?

Se imposti che il socket funzioni in modalità non bloccante, ogni chiamata a read leggerà solo i dati attualmente disponibili (se presenti). Quindi questo è effettivamente uguale a un timeout immediato.

Puoi impostare la modalità non bloccante su un socket con una funzione come questa:

int setnonblock(int sock) {
   int flags;
   flags = fcntl(sock, F_GETFL, 0);
   if (-1 == flags)
      return -1;
   return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}

(Per ulteriori informazioni sulla lettura da socket non bloccanti vedere il read pagina man)


Non dici qual è il sistema operativo, ma se stai utilizzando Linux, puoi usare la chiamata select. Restituisce se c'è qualcosa da leggere sul descrittore di file oppure puoi impostarlo in modo che vada in timeout se non c'è niente da leggere. Il codice di ritorno indica quale.


In alternativa a select() , per il caso specifico di una porta seriale (terminale) puoi usare tcsetattr() per mettere il descrittore di file in modalità non canonica, con un timeout di lettura.

Per fare ciò, disattiva il ICANON flag e impostare il VTIME carattere di controllo:

struct termios termios;

tcgetattr(filedesc, &termios);
termios.c_lflag &= ~ICANON; /* Set non-canonical mode */
termios.c_cc[VTIME] = 100; /* Set timeout of 10.0 seconds */
tcsetattr(filedesc, TCSANOW, &termios);

Nota VTIME è misurato in decimi di secondo e che il tipo utilizzato per esso è tipicamente un unsigned char , il che significa che il timeout massimo è di 25,5 secondi.


select() accetta 5 parametri, prima il descrittore di file più alto + 1, quindi un fd_set per la lettura, uno per la scrittura e uno per le eccezioni. L'ultimo parametro è uno struct timeval, utilizzato per il timeout. Restituisce -1 in caso di errore, 0 in caso di timeout o il numero di descrittori di file nei set impostati.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>

int main(void)
{
  fd_set set;
  struct timeval timeout;
  int rv;
  char buff[100];
  int len = 100;
  int filedesc = open( "dev/ttyS0", O_RDWR );

  FD_ZERO(&set); /* clear the set */
  FD_SET(filedesc, &set); /* add our file descriptor to the set */

  timeout.tv_sec = 0;
  timeout.tv_usec = 10000;

  rv = select(filedesc + 1, &set, NULL, NULL, &timeout);
  if(rv == -1)
    perror("select"); /* an error accured */
  else if(rv == 0)
    printf("timeout"); /* a timeout occured */
  else
    read( filedesc, buff, len ); /* there was data to read */
  close(filedesc);
}

Linux
  1. Come configurare un proxy inverso Nginx

  2. Variabili d'ambiente Linux:come leggere e impostare su un VPS Linux

  3. Come configurare il tunneling SSH

  4. Come chiamare una funzione Bash nello script Bash all'interno di Awk?

  5. Come chiamare la funzione C in C++, la funzione C++ in C (mix di C e C++)

Come configurare WordPress su un Raspberry Pi

Come impostare un Cron Job in Linux

Come leggere un file riga per riga in Bash

Come impostare o modificare il nome host su Linux

Come installare e configurare SeedDMS

Come aumentare il timeout nello stucco?