recv() Nonblocking durch fcntl()? select()?
-
Hallo allerseits.
Folgendes Problem:
Ich habe ein Testprogramm geschrieben (C unter Linux), welches Pakete zu einem Client sendet, der Client empfängt die Pakete und schickt sie unverändert zurück. Dann empfängt wiederum das Testprogramm die Pakete, überprüft sie und fährt in einer Schleife fort.
All das funktioniert tadellos, bis auf die Kleinigkeit, dass im Falle eines verlorenen Paketes, das Programm nicht aus der recv() Funktion zurückkehrt, um einen Timeout festzustellen.
Das ganze sieht bislang ungefähr so aus: (Pseudocode)int s; //socketdescriptor s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); struct sockaddr_ll socket_address; socket_address.sll_family = PF_PACKET; socket_address.sll_protocol = htons(ETH_P_IP); //ect. for (j = 0; j < framestosend; j++) { sendto(s, buffer, framelength, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); recv(s, buffer_read, framelength, 0); prüfe_auf_timeout(time); vergleiche_Pakete(buffer, buffer_read); }
Jetzt ist es natürlich so, dass bei einem Verlorenem Paket die Funktion recv(); endlos lange wartet und nicht auf ein Timeout hin geprüft werden kann. Natürlich werden über das Netzwerk viele andere „nutzlose“ Pakete gesendet, die dazu führen, dass recv() wieder erwacht. Allerdings will ich mich darauf nicht verlassen und es anständig machen.
Füge ich die verheißungsvolle Funktion fcntl() ein, die den Socketzugriff auf non-blocking schalten soll (wie ich es verstanden habe), dann wirft die Funktion recv() beim nächsten Zugriff ein -1 Errorcode zurück (Resource temporarily unavailable).
Beispiel:
fcntl(s, F_SETFL, O_NONBLOCK); // Rückgabewert 0 for (time=0; time < 5*sec; sec++) { recv(s, buffer_read, framelength, 0); //Rückgabe -1 prüfe_Paket(); }
Die alternative hierzu soll sein, mit select() vor dem Aufruf von recv() zu prüfen, ob Daten zum lesen vorhanden sind. Aber auch das klappt in meinem Versuch nicht:
tv.tv_sec = 2; //timeout für select tv.tv_usec = 0; FD_ZERO(&s); //FD_SET(0, &s); <compilerfehler Anfrage nach Element »__fds_bits« in etwas, was keine Struktur oder Variante ist if(select(1,&s,NULL,NULL,&tv)) { recv(s, buffer_read, framelength, 0); }
Problem: select liefert mir immer eine 0 zurück, egal ob sich Daten im Puffer befinden oder nicht. Außerdem wirft recv() nach dem aufruf von select eine -1 zurück „Socket operation on non-socket“.
Wäre für Hilfe dankbar.
-
Hab das Problem gelöst.
fcntl(s, F_SETFL, O_NONBLOCK);
hat zum Erfolg geführt.
Entgegen meiner Erwartungen, liefert dann recv(); "-1" zurück, wenn nichts zum schreiben vorliegt. Eigentlich habe ich "0" erwartet, für 0 bytes gelesen bzw. zum lesen vorhanden...
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.