mehrere winsock recv gleichzeitig abhandeln?
-
Der erste Thread ist überflüssig.
Die Verbindungen kannst du im selben Thread annehmen, in dem du auch die Daten empfängst.Hier siehst du wie es Beispielhaft gelöst wurde:
http://www.c-worker.ch/tuts/select.php#serverNachschauen, ob eine neue Verbindung angenommen werden kann.
// acceptSocket is im fd_set? => verbindung annehmen (sofern es platz hat) if(FD_ISSET(acceptSocket,&fdSet)) { // einen freien platz für den neuen client suchen, und die verbingung annehmen for(i=0;i<MAX_CLIENTS;i++) { if(clients[i]==INVALID_SOCKET) { clients[i]=accept(acceptSocket,NULL,NULL); printf("Neuen Client angenommen (%d)\n",i); break; } } }Nachschauen ob Daten empfangen werden können
// prüfen wleche client sockets im fd_set sind for(i=0;i<MAX_CLIENTS;i++) { if(clients[i]==INVALID_SOCKET) { continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array } if(FD_ISSET(clients[i],&fdSet)) { rc=recv(clients[i],buf,256,0); // prüfen ob die verbindung geschlossen wurde oder ein fehler auftrat if(rc==0 || rc==SOCKET_ERROR) { printf("Client %d hat die Verbindung geschlossen\n",i); closesocket(clients[i]); // socket schliessen clients[i]=INVALID_SOCKET; // seinen platz wieder freigeben } else { buf[rc]='\0'; // daten ausgeben und eine antwort senden printf("Client %d hat folgendes gesandt: %s\n",i,buf); // antwort senden sprintf(buf2,"Du mich auch %s\n",buf); send(clients[i],buf2,(int)strlen(buf2),0); } } }
-
doll schrieb:
hustbaer schrieb:
ThePro schrieb:
Die Profis machen das wohl überwiegend mit select.
Nein.
Wenn du eine Aussage schon definitiv verneinst, dann würde mich interessieren
was du denn dann für richtig hältst.Man verwendet üblicherweise andere de-multiplexer, wie z.B. IO Completion Ports, epoll oder kqueue.
-
hustbaer schrieb:
doll schrieb:
hustbaer schrieb:
ThePro schrieb:
Die Profis machen das wohl überwiegend mit select.
Nein.
Wenn du eine Aussage schon definitiv verneinst, dann würde mich interessieren
was du denn dann für richtig hältst.Man verwendet üblicherweise andere de-multiplexer, wie z.B. IO Completion Ports, epoll oder kqueue.
Gibt es diese Funktionen unter Windows überhaupt?
-
ThePro schrieb:
Der erste Thread ist überflüssig.
Die Verbindungen kannst du im selben Thread annehmen, in dem du auch die Daten empfängst.Okay, angenommen folgendes ergibt sich:
Eine Verbindung wurde in das Set eingetragen und mit select wird
gerade (wie in dem Beispiel) darauf gewartet dass dieser wieder lesbar wird.In der gleichen Zeit will der Benutzer eine neue Verbindung aufbauen.
Dann hängt das Programm doch immer noch bei Select (solang ich keinen Timeout setze - was ja bei C-Worker auch nicht der Fall ist), und kann die neue Verbindung nicht aufbauen solange der 'alte' Socket nicht noch einmal lesbar wurde (weil der neue ja noch garnicht eingetragen ist).
also:
- Socket1 wird ins Set eingetragen
- Mit Select wird darauf gewartet dass Daten am Socket1 kommen
- Es kommen Daten am Socket1
- Keine neuen Verbindungen, also wieder zu Select (blockiert, bis Socket1 lesbar, da ja nur Socket1 bisher im Set)
- Jetzt versucht der Benutzer eine neue Verb. aufzubauen-> klappt erst, sobald select nicht mehr blockiert,
--> und das blockiert erst nicht mehr wenn etwas am Socket1 kommt
-
Gibt es diese Funktionen unter Windows überhaupt?
Welche?
-
Du kannst einem der drei Sets einen 'Fake'-Socket hinzufügen.
Wenn du diesen aus einem anderen Thread mit closesocket schließt kehrt select zurück.Klingt zwar unsauber, aber anders wird es wohl nicht gehen.
-
MrNoname schrieb:
hustbaer schrieb:
doll schrieb:
hustbaer schrieb:
ThePro schrieb:
Die Profis machen das wohl überwiegend mit select.
Nein.
Wenn du eine Aussage schon definitiv verneinst, dann würde mich interessieren
was du denn dann für richtig hältst.Man verwendet üblicherweise andere de-multiplexer, wie z.B. IO Completion Ports, epoll oder kqueue.
Gibt es diese Funktionen unter Windows überhaupt?
IO Completion Ports ja, die anderen nein. Ich habe auch nicht behauptet dass diese Interfaces "portabel" wären. Man kann allerdings Wrapper um diese de-multiplexer bauen, so dass man auf allen Systemen das selbe Wrapper-Interface verwenden kann.
-
doll schrieb:
ThePro schrieb:
Der erste Thread ist überflüssig.
Die Verbindungen kannst du im selben Thread annehmen, in dem du auch die Daten empfängst.Okay, angenommen folgendes ergibt sich:
Eine Verbindung wurde in das Set eingetragen und mit select wird
gerade (wie in dem Beispiel) darauf gewartet dass dieser wieder lesbar wird.In der gleichen Zeit will der Benutzer eine neue Verbindung aufbauen.
Dann hängt das Programm doch immer noch bei Select (solang ich keinen Timeout setze - was ja bei C-Worker auch nicht der Fall ist), und kann die neue Verbindung nicht aufbauen solange der 'alte' Socket nicht noch einmal lesbar wurde (weil der neue ja noch garnicht eingetragen ist).
(...)Der "neue" ist noch nicht eingetragen, aber der Socket über den du Verbindungen annehmen möchtest, sollte eingetragen sein.
D.h. in deinem Beispiel hast du 1x den "listen socket" und 1x den "socket for connection 1" im FD_SET.select() kommt dann zurück, sobald entweder der "socket for connection 1" lesbar/schreibbar wird, ODER eine neue Verbindung am "listen socket" eingeht.
Lies dir die Doku zu select() durch, da sollte genau drin stehen, welche Bedingungen/Ereignisse für welches der drei Sets "gelten", so dass select() zurückkommt.p.S.: damit das gut funktioniert, sollte man den "listen socket" auch im non-blocking Modus betreiben (die "connection" Sockets sowieso). Sonst kann es einem passieren, dass listen() meldet es wäre eine Verbindung da, nur bis man accept() aufruft, ist die Gegenstelle futsch (antwortet nichtmehr oder hat schon ein RST geschickt). Dann würde accept() nämlich blockieren, und das wäre weniger gut. Im non-blocking Mode bekommt man in dem Fall von accept() einfach einen EWOULDBLOCK, und alles ist gut.
-
falls du "C++ von A bis Z" noch zur hand hast: darin wird (wenn ich mich noch recht erinnere) ausführlich auf select eingegangen und an einem tcp-client-server beispiel demonstriert...
-
hustbaer schrieb:
select() kommt dann zurück, sobald entweder der "socket for connection 1" lesbar/schreibbar wird, ODER eine neue Verbindung am "listen socket" eingeht.
super, jetzt macht das endlich sinn

-
Ahh sorry ich hatte nur das "Jetzt versucht der Benutzer eine neue Verb. aufzubauen" gelesen und daraus geschlossen das du einen Client programmierst wo der Benutzer dynamisch Verbindungen herstellen kann.
Für einen Server macht mein Vorschlag mit dem Fake-Socket dann keinen Sinn.
-
------ schrieb:
Ahh sorry ich hatte nur das "Jetzt versucht der Benutzer eine neue Verb. aufzubauen" gelesen und daraus geschlossen das du einen Client programmierst wo der Benutzer dynamisch Verbindungen herstellen kann.
Für einen Server macht mein Vorschlag mit dem Fake-Socket dann keinen Sinn.
danke trotzdem, für deine mühe! und aller anderen natürlich
