Socketprogrammierung: SO_LINGER/Timeout (Linux)
-
Hallo Community,
hoffe bin im richtigen Sub aber denke schon
Und zwar schreibe ich grade an einem Server/Client zur einfachen Bildübertragung auf Socketbasis und entsprechendem Kommunkationsprotokoll. Ich bin eigentlich auch schon fertig es gibt nur eine Sache die mich stört und die ich gerne umgesetzt bekommen möchte.
Und zwar bekommt der Server Metadaten zu dem Bild vom Client und u.A. die Bildgröße, damit dieser weiß, wieviel Bytes er zu empfangen hat. Hier vielleicht erstmal der Code:
image = fopen(imagename, "wt"); int int_imagesize = atoi(*(&imagesize)); int bytesToReceive = int_imagesize; int bytesReceived = 0; while(bytesReceived < bytesToReceive) { int len = read(sock_client, &buf_image[bytesReceived], bytesToReceive - bytesReceived); bytesReceived += len; } int i = 0; while(i < bytesToReceive) { fputc(buf_image[i], image); i++; } fclose(image);
Nur will ich aber den Fall abfangen, das der Client weniger Daten schickt als der Server erwartet. Lässt sich ja einfach Testen indem ich 'bytesToReceive' manuel niedriger setze als es sein dürfte. Nun kehrt read bzw. die Schleife nicht zurück und der Server hängt sich quasi auf bzw anderums er schreibt logischerweise zu wenig Daten(das natürlich nur wenn ich 'bytesToReceive' fake; kommen wirklich zu wenig Daten an trifft ersters ein). Von meinem Prof habe ich mir sagen lassen, das die SO_LINGER Option, die man mit setsockopt und der struct setzt, helfen könnte da diese den Timeout/Close veranlasst wenn read() bedingt durch fehlende Daten veranlasst. Gesagt getan, SO_LINGER auf on gesetzt und linger auf 1. Jedoch ohne erfolg. Nach meinen Recherchen dürfte die Ausage des Prof eh nicht stimmen?
Zumal bringt mir ein close() nix, da eigentlich der Client über die Fehlenden Bytes informiert werden soll um die Übertragung erneut zu beginnen.
Es hat alles bis jetzt relativ problemlos geklappt nur hier komme ich nicht weiter
Eventuell auch lösbar mit dem return-Value von read()?!Hoffe ein paar Anregungen zu bekommen (in jegliche Richtung
)
-
Wie kann es denn sein, daß der Client dem Server mitteilt, daß er x Byte schickt, und dann aber weniger schickt?
-
Das kann passieren da es UDP basierend ist oder aber wenn ein Fehler beim Client auftritt!
Keine Ahnung vielleicht ist es auch ein dummer Gedanke aber wenn zB. bei einem Netzwerkspiel keine Daten kommen(ja auch UDP) laggt es oder es kommt Timeout. Das will ich quasi abfangen.
Vielleicht noch ein Bsp:
Ich schicke weiterhin eine Checksum von dem Bild mit. Falls diese mit der Checksum, die auf dem Server berechnet wurde nicht übereinstimmt, bekommt der Client ein RST und soll nocheinmal die Metadaten schicken. Den Server setze ich in diesem Fall wieder auf read() 'zurück'. Falls nun aber der Benutzer (ich weiß sehr konstruiert) nicht reagiert und das neusenden bestätigt, kann der Server mit read() nix lesen. Nun will ich folglich das der Client einen Timeout bekommt!Quasi das read() irgendwann zurückkehrt was wohl mit der SO_LINGER Opt gehen soll...
-
Okay, okay, ich dachte mehr an TCP. Von UDP habe ich keinen Plan. Aber Du kannst mit select erfragen, ob für einen Socket Daten zum Empfang bereitstehen. select kannst Du auch einen TimeOut-Parameter mitgeben, so daß es nach Erreichen des TimeOuts auch zurückkehrt, wenn keine Daten gelesen werden können.
-
So klappt jetzt das mit LINGER war totaler Blödsinn.
Nutze nun SO_RCVTIMEO für den Timeout. Klappt wunderbar habe nur ewig gebraucht es richtig anzuwenden bzw. es erstmal zu finden
Bekomme dadurch mit wenn read auf Grund fehlender Bytes endlos läuft und kann die Schleife mit einer entsprechnen Msg an den Client verlassen.
Danke dir Belli trotzdem guter Tip mit dem Select(). Das Problem dort war aber das Select() schon bei nur einem Byte 'ready' returned. Trotzdem werde ich das verwenden wenn u.A. die Checksum net stimmt und der benutzer aber die Eingabe nicht nochmal wiederholt.
-
J2T schrieb:
Das Problem dort war aber das Select() schon bei nur einem Byte 'ready' returned.
Das KANN bei read auch passieren.