Klassen-Design für Server-Verbindungen
-
Hallo C++ler,
ich hab mal wieder eine Frage.
Um im Denken in der Objektorientierung ein bisschen fitter zu werden habe ich mir vorgenommen, ein kleiens Projekt zu schreiben, in dem ich weitgehendst objektorientiert arbeiten will.
Allerdings stehe ich gerade vor einem kleinen Problem.
Ich hatte vor, für (das Server-Programm) pro zu lauschendem Port eine Instanz einer Klasse CServerConnection zu benutzen. Diese hat von CConnection geerbt. Wenn eine Anfrage an den Server kommt, öffnet dieser einen neuen Port und verwendet diesen für die Kommmunikation mit dem gerade angekommenem Clienten. Die Verbindung zum Clienten möchte ich auch gern als Objekt darstellen, allerdings fehlt mir die Idee, wie ich das Ganze mit der CServerConnection-Instanz verbinde.
Mit einer Liste, oder einem Vector? Oder etwas gänzlich anderes?
Ich bräuchte deswegen jetzt die Hilfe und einen Tipp, wie ich das organisiere und trotzdem nicht allzu unperformant bleibe!
Grüße,
Mao
-
Wie Client, Server?
Über Sockets?
Wo soll dann eine Liste bzw. ein Vektor ins Spiel kommen? Verstehe ich nicht so ganz.
-
Hallo,
hm, okay ich versuch nochmal das zu Erklären, ist ja aller Wahrscheinlichkeit nicht so ganz klar rübergekommen.

Ich möchte eine kleine Server-Software von Anfang an objektorientiert aufziehen. Dazu habe ich eine Basisklasse "CConnection", die Sachen wie den Socket-Descriptor, WSAData-Struktur und Funktionen wie das Senden und Empfangen von Zeichenketten.
Die Klasse "CServerConnection" ist von "CConnection" abgeleitet. Sie implementiert die Funktionen wie auf einem Port zu lauschen, die Anzahl der Verbindungen zurückzugeben, zu begrenzen, zu sperren, ...
Und wenn ein Client auf den späteren Server zugreift, greif ich ihn mit accept() ab und er bekommt auf dem Server-Rechner einen anderen Port vom Betriebssystem zugewiesen.
Nun möchte ich aber die ganzen Verbindungen zu den Clients innerhalb von "CServerConnection" verwalten und weiß nicht so ganz, wie ich das am Besten mache.
Grüße,
Mao
-
Aaaah, ich denke jetzt hab ich's.
Hat zwar mit deiner Frage nix zu tun, aber erstmal vorweg...greif ich ihn mit accept() ab und er bekommt auf dem Server-Rechner einen anderen Port vom Betriebssystem zugewiesen.
Hier liegt ein Misverständnis vor: du bekommst vom OS keinen neuen Port, du bekommst nur einen neuen Socket der eben mit dem Client verbunden ist. Ist im Prinzip egal, erklärt aber wie mit TCP/IP mehr als 64k Connections zu einem Server möglich sind, trotz 16 Bit Portnummern-Limit.
Zu deiner Frage: ich denke das hängt davon ab wie du auf die Liste Zugriff brauchst. Im einfachsten Fall brauchst du garkeine Liste, weil du für jede Connection einen eigenen Thread rausstartest, und der alles angeforderten Resourcen wieder freigibt. Wenn du asynchrones IO verwendest brauchst du u.U. mehrere Listen.
Wenn du einfach nur die Connections alle gesammelt irgendwo haben willst, damit du z.B. weisst wieviele es gleichzeitig sind, oder an alle ein "kill" Signal schicken kannst wird ein std::set<ClientConnection*> reichen, oder ein boost::ptr_vector<ClientConnection> oder sowas.
Solltest du den Fall haben dass du z.B. ausgehend vom SOCKET Deskriptor den ClientConnection Zeiger nachschlagen willst bietet sich ein map an (normale map oder boost::ptr_map - je nachdem). etc.
Was gut & richtig ist hängt IMO davon ab wie du IO handhabst. Für asynchrones "proaktives" IO (z.B. IO Completion Ports) brauchst du nicht viele Listen (u.U. garkeine), da das OS bereits die nötigen Listen intern verwaltet.
Wenn du dagegen "normales reaktives" asynchrones IO mit select machst wirst du auf jeden Fall eine Liste brauchen um das FD_SET für select zusammenzubasteln.
-
hustbaer schrieb:
Hier liegt ein Misverständnis vor: du bekommst vom OS keinen neuen Port, du bekommst nur einen neuen Socket der eben mit dem Client verbunden ist. Ist im Prinzip egal, erklärt aber wie mit TCP/IP mehr als 64k Connections zu einem Server möglich sind, trotz 16 Bit Portnummern-Limit.
wenn der server nur auf einem tcp-port lauscht (etwa http-port 80), sind von einem rechner aus natürlich nur 64k gleichzeitige connections zu diesem server möglich und ein neuer socket bedeutet auch immer eine neue lokale portnummer. tu bitte nicht immer so, als wenn du von diesen dingen etwas verstehen würdest, mein lieber hustenbär.

-
Hi,
danke für die Antworten erstmal!
Ich wollte das Ganze eigtl. in nur einem Thread realisieren (a la lighttpd), allerdings seh ich ein, dass es wohl erstmal leichter ist, voneinander unabhängige Threads zu verwenden. (Hatte noch ein zusätzliches Chat-Gespräch mit jmd., der ein ähnliches Problem hatte.)Da ich wahrscheinlich eh nicht mit der Masse an gleichzeitigen Clients überflutet werde, wird das jetzt auch nicht so dramatisch sein.
Bei passender Gelegenheit werde ich es trotzdem nochmal ohne Threads probieren!
Grüße,
Mao
-
Ports of Madness schrieb:
hustbaer schrieb:
Hier liegt ein Misverständnis vor: du bekommst vom OS keinen neuen Port, du bekommst nur einen neuen Socket der eben mit dem Client verbunden ist. Ist im Prinzip egal, erklärt aber wie mit TCP/IP mehr als 64k Connections zu einem Server möglich sind, trotz 16 Bit Portnummern-Limit.
wenn der server nur auf einem tcp-port lauscht (etwa http-port 80), sind von einem rechner aus natürlich nur 64k gleichzeitige connections zu diesem server möglich und ein neuer socket bedeutet auch immer eine neue lokale portnummer. tu bitte nicht immer so, als wenn du von diesen dingen etwas verstehen würdest, mein lieber hustenbär.

Von einem Rechner zu einem anderen Rechner kann es max. 64k Connections geben. Und hab ich was anderes geschrieben?
Und ein neuer Socket der von accept kommt bedeutet KEINE (neue) lokale Portnummer. Das Limit 1 PC <-> 1 anderer PC = max. 64k Connections kommt daher dass auf dem Client (jener der connect() aufruft) für jede Verbindung eine Portnummer gebraucht wird. Am Server ist das nicht so.
Daher kann ein Server *von verschiedenen anderen Rechnern* auch mehr als 64k Connections annehmen.Also tu du mir bitte einen Gefallen und schreib nicht über Dinge von denen du nix verstehst.
-
benutz doch boost asio
-
hustbaer schrieb:
Von einem Rechner zu einem anderen Rechner kann es max. 64k Connections geben. Und hab ich was anderes geschrieben?
immer noch falsch. von einem rechner zu einem anderen kann es maximal theoretisch 64k*64k connections geben (vorausgesetzt auf beiden ist nur 1 tcp-stack vorhanden).
hustbaer schrieb:
Und ein neuer Socket der von accept kommt bedeutet KEINE (neue) lokale Portnummer.
wenn schon eine verbindung besteht (local_address/local_port <---> remote_address/remote_port) muss der client eine andere lokale portnummer wählen, damit ein weiter, eindeutiger kommunikationskanal geöffnet wird.
husti, husti, du enttäuschst mich immer wieder.

-
Ja, Troll.