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);
}