Hinweis: Das Forum wird geschlossen! Neue Registrierungen sind nicht mehr möglich!

 Zurück zu Pro-Linux   Foren-Übersicht   FAQ     Suchen    Mitgliederliste
Probleme mit select() und nichtblockierendem Socket

 
Neuen Beitrag schreiben   Auf Beitrag antworten    Pro-Linux Foren-Übersicht -> Programmieren - C
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
ElBlues



Anmeldungsdatum: 25.03.2008
Beiträge: 127

BeitragVerfasst am: 06. Okt 2010 19:45   Titel: Probleme mit select() und nichtblockierendem Socket

Ich glaube, ich habe hier ein grundsätzliches Verständnisproblem:

Ich habe einen Server, bei dem ich mit select() auf eingehende Daten und neue Verbindungen checke. Das funktioniert prinzipiell auch ganz gut. Sockets von eingehenden Verbindungen werden immer auf non-blocking gesetzt, so dass ich kontrollieren kann, wie lange die Empfangsroutine dauert (da ich nicht unbegrenzt lange an größeren Datenblöcken herumladen will und dabei die anderen Clients vernachlässige).

Das führt jetzt allerdings zu folgendem Effekt, wenn ein Client nach dem Connect sehr schnell Daten sendet:

1. select() kommt zurück, weil sich ein Client verbindet -> dieser wird akzeptiert
2. der Socket dieses Clients wird auf non-blocking gesetzt
3. es wird versucht, Daten mit recv() zu empfangen -> es wird nichts empfangen, recv() kehrt sofort zurück
4. es wird erneut select() aufgerufen -> dieses blockiert jetzt bis in alle Ewigkeit

Scheinbar sind die Daten schon da, so dass select() nichts mehr melden kann, recv() konnte sie aber noch nicht abholen.

Was nun? Wie erfahre ich, ob irgend einer der Sockets noch nicht empfangene Daten hat, wenn ich select() dafür nicht verwenden kann?
_________________
http://www.kaufkauf.net - nie wieder Einkäufe vergessen!
 
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen

Janka



Anmeldungsdatum: 11.02.2006
Beiträge: 3569

BeitragVerfasst am: 06. Okt 2010 22:45   Titel:

Du schreibst von "wenn sich ein Client verbindet" und "Connect" andererseits benutzt du recv(). Welches Protokoll verwendest du überhaupt?

Aber ohne Beispielcode kann man dir eh nicht vernünftig helfen, weil man das Problem nicht nachvollzogen bekommt.
Bereite erst einmal ein simples, kompilierbares Beispiel (Server und Client) vor, das das unerwünschte Verhalten zeigt.

Janka
_________________
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.
 
Benutzer-Profile anzeigen Private Nachricht senden

ElBlues



Anmeldungsdatum: 25.03.2008
Beiträge: 127

BeitragVerfasst am: 07. Okt 2010 7:19   Titel:

Der Ablauf ist eigentlich nicht kompliziert:

1. Der Server wartet mit select(), ob auf irgend einem Socket eine Leseoperation stattfindet, der Serversocket ist dabei teil des FD-Set, das von select() überwacht wird
2. Ein Client verbindet sich mit dem Server, select() kommt zurück und der Client wird mit accept() angenommen; des weiteren wird der Clientsocket auf nicht-blockierend gesetzt
3. Es wird sofort versucht, mit recv() von diesem Clientsocket Daten zu lesen -> das klappt nicht, der Fehlercode sagt aus, dass recv() an dieser Stelle eigentlich blockieren würde

-> irgend wann hier trudeln die Daten vom Client tatsächlich ein

4. Der Code kehrt zu select() zurückt, es werden jetzt die Sockets des Servers und des Clients überwacht, allerdings meldet select() jetzt nicht, dass Daten da wären (vermutlich, weil diese Daten schon in einem internen Puffer sind?)

Wenn ich im Schirtt 4. das select() unterdrücke und einfach wiederholt recv() für diesen Client aufrufe, dann erhalte ich meine Daten.
_________________
http://www.kaufkauf.net - nie wieder Einkäufe vergessen!
 
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen

hjb
Pro-Linux


Anmeldungsdatum: 15.08.1999
Beiträge: 3236
Wohnort: Bruchsal

BeitragVerfasst am: 07. Okt 2010 10:23   Titel:

Hi!

EWOULDBLOCK besagt, dass noch keine Daten da sind. Man muss eine Schleife darum basteln und aus Effizienzgründen auch mit select auf Daten warten. Es ist klar, dass unmittelbar nach dem accept noch keine Daten da sind. Jedenfalls nicht immer.

Grüße,
hjb
_________________
Pro-Linux - warum durch Fenster steigen, wenn es eine Tür gibt?
 
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger

ElBlues



Anmeldungsdatum: 25.03.2008
Beiträge: 127

BeitragVerfasst am: 07. Okt 2010 17:03   Titel:

Das ist doch aber gerade der Knackpunkt: Nach diesem EWOULDBLOCK muss ich mich darum kümmern, ob andere Clients was wollen bzw. ob sich neue Clients verbinden.

Also rufe ich select() auf - was aber blockiert, obwohl inzwischen Daten für diesen Socket da wären!
_________________
http://www.kaufkauf.net - nie wieder Einkäufe vergessen!
 
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen

hjb
Pro-Linux


Anmeldungsdatum: 15.08.1999
Beiträge: 3236
Wohnort: Bruchsal

BeitragVerfasst am: 08. Okt 2010 10:23   Titel:

Hi!

Wenn das select blockiert, sind eben noch keine Daten da. Oder du verwendest den falschen Dateideskriptor.

Wenn das Programm nichts weiter zu tun hat als alle Clients zu bedienen, dann musst du die Dateideskriptoren aller Clients in das select aufnehmen, und wenn select zurückkommt, prüfen, welche zu bearbeiten sind.

Grüße,
hjb
_________________
Pro-Linux - warum durch Fenster steigen, wenn es eine Tür gibt?
 
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen MSN Messenger

Beiträge vom vorherigen Thema anzeigen:   
     Pro-Linux Foren-Übersicht -> Programmieren - C Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehen Sie zu:  

Powered by phpBB © phpBB Group
pro_linux Theme © 2004 by Mandaxy