Wenn Sie den Socket so einstellen, dass er im nicht blockierenden Modus betrieben wird, liest jeder Aufruf von read nur die aktuell verfügbaren Daten (falls vorhanden). Dies entspricht also effektiv einem sofortigen Timeout.
Sie können den nicht blockierenden Modus für einen Socket mit einer Funktion wie dieser einstellen:
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);
}
(Weitere Informationen zum Lesen aus nicht blockierenden Sockets finden Sie im read
Manpage)
Sie sagen nicht, was das Betriebssystem ist, aber wenn Sie unter Linux laufen, könnten Sie den select-Aufruf verwenden. Es kehrt zurück, wenn im Dateideskriptor etwas zu lesen ist, oder Sie können es so einrichten, dass es abläuft, wenn nichts zu lesen ist. Der Rückgabecode gibt an, welche.
Alternativ zu select()
, für den speziellen Fall einer seriellen Schnittstelle (Terminal) können Sie tcsetattr()
verwenden um den Dateideskriptor in den nicht-kanonischen Modus zu versetzen, mit einem Lese-Timeout.
Deaktivieren Sie dazu die ICANON
Flag und setzen Sie VTIME
Steuerzeichen:
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);
Beachten Sie VTIME
in Zehntelsekunden gemessen wird und dass der dafür verwendete Typ typischerweise ein unsigned char
ist , was bedeutet, dass das maximale Timeout 25,5 Sekunden beträgt.
select() nimmt 5 Parameter, zuerst den höchsten Dateideskriptor + 1, dann ein fd_set zum Lesen, eines zum Schreiben und eines für Ausnahmen. Der letzte Parameter ist ein Struktur-Zeitwert, der für die Zeitüberschreitung verwendet wird. Es gibt -1 bei einem Fehler, 0 bei Zeitüberschreitung oder die Anzahl der Dateideskriptoren in den gesetzten Sätzen zurück.
#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);
}