mehre socketverbindungen an server gleichzeitig
-
hallo,
wie kriege ich es hin, das mein tcp server mehrere verbindung annehmen kann? sobald mein server die erste verbindung angenommen hat, wartet er dort auf daten (recv()) und während dessen ist ja alles geblockt. nennt sich glaub ich auch blocking-call oder so ähnlich?!?
was muss ich machen, damit ich weiterhin auf verbindungen warten kann, während andere clients bereits eine verbindung zu meinem server aufgebaut haben?
-
Ist dein Problem die anderen Clients anzunehemn, oder das diese dann nichts schicken können?
Mfg Ominion
-
Hallo Joachim,
da gibt es verschieden Möglichkeiten:
1:
Setze den Socket auf nonblocking. Dann kommt recv immer gleich wieder zurück. Wenn er blockieren würde bekommst du die Fehlermeldung WSAEWOULDBLOCK.2:
Schau dir mal select an. Sobald ein Socket was für dich hat kommt der select zurück. Dann kannst du abfragen welchen socket du bearbeiten musst. Da kannst du auch timeouts angeben.3:
Spendiere für jeden Client einen Thread.Alles hat seine Vor- und Nachteil … wie immer im Leben

Gruß
Volker
-
Der Server muß halt wieder beim accept landen. Willst Du gleichzeitig auf Daten von einem Client (recv) und auf neue Verbindungen warten, gibt es mehrere Möglichkeiten:
- mit fork() einen Prozess pro client erzeugen (Unix/Linux)
- ein Thread pro Dateideskriptor
- mittels poll oder select alle Dateideskriptoren überwachen und dann nicht blockierend lesenTntnet
edit: ok Volker war schneller
- dafür ist sein 1. Vorschlag unvollständig und mein Vorschlag mit fork ist nicht dabei :p
-
ah ok,
das mit den threads hört sich am besten an...(behaupte ich mal :P)
sobald ich also einen connect hab erzeuge ich einen thread der diese verbindung behandelt (snd/recv) während der server wieder in den listen-modus geht und darauf wartet das was passiert?!?(Theorie so richtig?)
Die Sache mit dem Non-Blocking Call, wie funktioniert das? Muss ich da einen Parameter bei der Erzeugung setzen?!?
danke für die ideen.
-
[quote="Joachim2006"]ah ok,
das mit den threads hört sich am besten an...(behaupte ich mal :P)
quote]
Und schon wieder eine falsche Behauptung mehr auf der Welt

Die Antwort lautet, es kommt drauf an. Wenn Du nur eine handvoll sockets aufmachen willst, ist diese Vorgehensweise ok. Sind es dagegen viele Sockets, sagen wir mal 500+, dann verbraucht die reine Verwaltung der Threads am Ende mehr Performance als alles andere zusammen.
Da von der Theorie her ohnehin nie mehr Sachen gleichzeitig passieren können wie Du Prozessoren (bzw. Cores) hast, ist es aus Performancesicht meistens besser mit einem Thread und select zu arbeiten.
Multithreading hat einen Preis, der durch die Verwaltung der Threads und die Context-switches erzeugt wird. Man sollte sich daher gut überlegen wann und wie viele Threads man erzeugt...
Eine Idee für deine Situation: Nimm einen Thread der nur auf die socket wartet und die einkommenden Packete in ein Message-Queue schreibt.
Nimm einen zweiten Thread der die Pakete aus dem queue nimmt und weiteverarbeitet. Bei Bedarf kannst du auch mehr als einen worker-Thread nehmen um den Prozessor besser auszulasten. (denn as ist es wofuer Multithreading eigendlich gut ist, den Prozessor optimal auslasten bis er halt 100% ereicht...)
-
es reicht doch theoretisch 1 thread, du legst dir nen vector<SOCKET> an, und nen server-socket.
jetzt nimmst du 2 fd_set einer zu lesen einer für error(NIE das FD_ZERO vergessen um das set zu löschen), tust deinen ServerSocket rein, fährst ein select, ist das ergebnis > 1, prüfst du ob an deinem serversocket was anliegt, ist dem so holst du mit accept den client, schiebst ihn in den vektor und gehst ans ende der schleife, dort füllst du deine fd_set wieder (ServerSocket + Clients(sofern vorhanden)) fährst wieder ein select, ist auch hier wieder > 1 dann prüfst du erst deinen serversocket und anschliessend alle sockets die sonst noch im fd_set fürs lesen stehen auf daten, verarbeitest sie, oder WENN recv = 0 ergibt löschst du sie.
JA ich weis das da noch einiges optimiert werden kann, aber hey ihr wollt sicher auch noch was beitragen :p
-
Das ist Volkers Lösungsvorschlag 2.
Warum schlägst Du std::vector vor? Von der Logik her wäre es ein std::set - nämlich eine ungeordnete Liste (um mal wieder was C++-mässiges einzubringen
).
-
hast ja recht, vor allem da man das set einfach nur kopieren brauch und nich umständlich aus dem vektor socket für socket zu kopieren muss
ausserdem hab ich 2. nur etwas weiter ausformuliert, weil ich die verwendung von threads in c++ etwas zu platformabhängig finde