|
You last visited: Today at 06:06
Advertisement
C++ Server Paket Entwurfsmuster
Discussion on C++ Server Paket Entwurfsmuster within the C/C++ forum part of the Coders Den category.
12/07/2013, 15:46
|
#1
|
elite*gold: 0
Join Date: Oct 2013
Posts: 135
Received Thanks: 44
|
C++ Server Paket Entwurfsmuster
Hi,
ich bin gerade am überlegen wie ein Entwurfsmuster meiner Paket Klasse die für einen Game Server fungieren soll aussehen könnte.
PacketBuffer (Buffer für die empfangenen Pakete bzw. zum senden)
PacketFilter (Unbekannte Pakete etc. filtern)
PacketHandler (Pakete parsen und Callback Funktionen aufrufen z.B. wenn es sich um das Login Packet handelt)
PacketLog (Zum protokollieren der Pakete in eine .txt Datei)
PacketEncoding (Dient dazu um die Pakete zu verschlüsseln / entschlüsseln)
Mein Gedanke währe jetzt folgender:
Receive Packet:
Session -> PacketBuffer -> PacketEncoding -> PacketLog -> PacketFilter -> PacketHandler -> Klasse die das Packet handled
Send Packet:
Session -> PacketBuffer -> PacketEncoding -> PacketLog
Passt das so?
Außerdem muss ich noch irgendwo die Packete für den PacketHandler registrieren und den dazugehörigen Callback binden.
Bei dem Server habe ich das mehr oder weniger von den boost examples übernommen.
Klasse: Server
Startet die Servercore und beginnt neue Verbindungen anzunehmen.
Bei einer neuen Verbindung wird ein shared Objekt der Klasse 'Session' erstellt und in den Parametern das Socket übergeben sowie eine Referenz der Klasse SessionList.
Klasse: Session
Leitet von der Klasse Client sowie der Klasse std::enable_shared_from_this<T> ab.
Im Konstruktor wird der Socket und eine Referenz der SessionList erwartet, beide werden als Member gespeichert.
Außerdem wird die Session in die SessionList hinzugefügt und bei Verbindungsabbrüchen etc. wieder entfernt.
Klasse: Client
Enthält pure virtuelle Schnittstellen z.B. send.
Klasse: SessionList
Enthält virtuelle Funktionen für das sammeln von shared Client Objekten in einem Container und weitere virtuelle Funktionen.
Btw. In die Session Klasse würde ich alle Header wie Character, Account etc. packen und für alles eine Membervariable erstellen. Das Problem an der Sache ist aber, das die Session ja eig. nur einen indirekten Bezug zu dem Zeug wie z.B. Character hat und es somit bad practice ist, oder nicht?
Ansonsten schönes Wochenende euch noch.
|
|
|
12/07/2013, 16:05
|
#2
|
elite*gold: 1
Join Date: Apr 2010
Posts: 13,772
Received Thanks: 15,036
|
Sieht soweit in Ordnung aus, nur verstehe ich den Unterschied bzw. den Sinn von PacketFilter und PacketHandler nicht.
Quote:
PacketFilter (Unbekannte Pakete etc. filtern)
PacketHandler (Pakete parsen und Callback Funktionen aufrufen z.B. wenn es sich um das Login Packet handelt)
|
Das kann man doch auch vereint in den PacketHandler packen :O
|
|
|
12/07/2013, 17:19
|
#3
|
elite*gold: 0
Join Date: Oct 2013
Posts: 135
Received Thanks: 44
|
Quote:
Originally Posted by Omdihar
Sieht soweit in Ordnung aus, nur verstehe ich den Unterschied bzw. den Sin von PacketFilter und PacketHandler nicht.
Das kann man doch auch vereint in den PacketHandler packen :O
|
Oh, stimmt, ich weiß jetzt auch nicht wie ich darauf gekommen bin.
Quote:
|
Btw. In die Session Klasse würde ich alle Header wie Character, Account etc. packen und für alles eine Membervariable erstellen. Das Problem an der Sache ist aber, das die Session ja eig. nur einen indirekten Bezug zu dem Zeug wie z.B. Character hat und es somit bad practice ist, oder nicht?
|
Weißt du vielleicht auch hier was zu?
|
|
|
12/07/2013, 17:24
|
#4
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
Quote:
|
Leitet von der Klasse Client sowie der Klasse std::enable_shared_from_this<T> ab.
|
Sicher, dass du Shared-Pointer oder überhaupt Pointer brauchst?
Quote:
|
Enthält virtuelle Funktionen für das sammeln von shared Client Objekten in einem Container und weitere virtuelle Funktionen.
|
Warum kein std::vector innerhalb der Server-Klasse?
Quote:
|
In die Session Klasse würde ich alle Header wie Character, Account etc. packen und für alles eine Membervariable erstellen. Das Problem an der Sache ist aber, das die Session ja eig. nur einen indirekten Bezug zu dem Zeug wie z.B. Character hat und es somit bad practice ist, oder nicht?
|
Kannst du das näher erläutern? Was genau willst du alles in der Session haben und wieso?
|
|
|
12/07/2013, 18:29
|
#5
|
elite*gold: 0
Join Date: Oct 2013
Posts: 135
Received Thanks: 44
|
Quote:
Originally Posted by MrSm!th
Sicher, dass du Shared-Pointer oder überhaupt Pointer brauchst?
|
boost::asio::ip::tcp::socket ist noncopyable und es gäbe noch andere Probleme.
Deswegen nutze ich shared Pointer.
Quote:
Originally Posted by MrSm!th
Warum kein std::vector innerhalb der Server-Klasse?
|
Ich könnte einen std::vector(ich glaube std::set eignet sich besser?) mit shared Pointern anlegen, allerdings gibt es im Spiel auch unterschiedliche Maps mit Spielern, dort würde ich dann einfach von der SessionList ableiten.
Die SessionList bietet ja dann die Funktion an allen eingetragenen Sessions in der Liste ein Paket zu senden.
Das mit der Map ist allerdings nicht das einzigste.
Bei einem std::vector müsste ich dann nochmal überall die nötigen Funktionen extra implentieren.
Quote:
Originally Posted by MrSm!th
Kannst du das näher erläutern? Was genau willst du alles in der Session haben und wieso?
|
Im Game Server werden die Accountdaten und eine Sessionid empfangen, diese müssten nochmal geprüft werden (Sessionid erstellt der Login Server).
D.h. ich brauch schonmal eine Klasse 'Accounts' oder so ähnlich.
Es besitzt auch jeder Account einen oder mehrere Charactere diese verfügen ein Inventar, Equipment, Statuswerte etc.
In der Account Klasse würde ich jetzt alle anderen Header wie die Character Klasse includen und anschließend in der Session.h die Account.h includen.
Mein vorhaben war dann, in der Session Klasse die Account Klasse als Member zu deklarieren.
Der PacketHandler called dann später die Callback Funktion wo das zerpflückte Packet übergeben wird und einen Pointer von der Session.
Dort wird dann alles gehandled und die getters/setters aufgerufen indem dann über dem Session Pointer auf die Eigenschaften wie z.B. CharacterInventory zugegriffen wird.
Nur bin ich jetzt etwas verunsichert, weil ich das Gefühl habe es ist ein unschöner Weg?
|
|
|
12/07/2013, 20:52
|
#6
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
|
Quote:
Originally Posted by EasyTale
boost::asio::ip::tcp::socket ist noncopyable und es gäbe noch andere Probleme.
Deswegen nutze ich shared Pointer.
|
Warum keine Referenzen? Die sind grundsätzlich zu bevorzugen. Damit meine ich deine gesamte Session. Die kannst du ebenfalls Single-Instance-mäßig gestalten, dann muss auch nichts kopiert werden.
Quote:
|
(ich glaube std::set eignet sich besser?)
|
Wieso?
Die Frage meine ich ernst, so fit bin ich auch nicht, was die Standard-Container angeht
Quote:
|
mit shared Pointern anlegen, allerdings gibt es im Spiel auch unterschiedliche Maps mit Spielern, dort würde ich dann einfach von der SessionList ableiten.
|
Um diesen Gedankengang nachvollziehen zu können, müsste man mehr über dein Gesamtdesign wissen. Alleine aus dem Netzwerk-Design erschließt sich das mir jetzt nicht.
Quote:
Im Game Server werden die Accountdaten und eine Sessionid empfangen, diese müssten nochmal geprüft werden (Sessionid erstellt der Login Server).
D.h. ich brauch schonmal eine Klasse 'Accounts' oder so ähnlich.
Es besitzt auch jeder Account einen oder mehrere Charactere diese verfügen ein Inventar, Equipment, Statuswerte etc.
In der Account Klasse würde ich jetzt alle anderen Header wie die Character Klasse includen und anschließend in der Session.h die Account.h includen.
Mein vorhaben war dann, in der Session Klasse die Account Klasse als Member zu deklarieren.
|
Ok, das klingt erstmal sinnig. Je nach Design könnte natürlich auch eine Art Player-Klasse einen Verweis auf die aktive Session haben, die die nötigen Handler in der Session registriert.
Quote:
|
Der PacketHandler called dann später die Callback Funktion wo das zerpflückte Packet übergeben wird und einen Pointer von der Session.
|
Auch hier gilt: Wenn du keinen Grund hast, der explizit für einen Pointer spricht, würde ich eine Referenz nehmen.
Quote:
|
Dort wird dann alles gehandled und die getters/setters aufgerufen indem dann über dem Session Pointer auf die Eigenschaften wie z.B. CharacterInventory zugegriffen wird.
|
Du könntest auch Funktionsobjekte als Callbacks (ich gehe mal fast davon aus, dass du stinknormale Function-Pointer verwendest; siehe std::function) verwenden, dann kannst du einfach eins registrieren, dass selbst den entsprechenden Account/Character/etc. kennt, dann braucht die Session den nicht zu kennen.
Quote:
|
Nur bin ich jetzt etwas verunsichert, weil ich das Gefühl habe es ist ein unschöner Weg?
|
Nunja, da wo Abhängigkeit bestehen muss, da ist sie letztendlich auch unumgänglich und kann nicht Bad Practice sein. Irgendwie muss eine Session nunmal zum Player/Account gehören. In welche Richtung das geht, hängt letztendlich auch vom restlichen Design ab, man kann nicht grundsätzlich einen Weg als falsch darstellen.
|
|
|
12/07/2013, 23:00
|
#7
|
elite*gold: 1
Join Date: Apr 2010
Posts: 13,772
Received Thanks: 15,036
|
Für das mit der Wahl der Standart Container habe ich hier ein schönes Bild
|
|
|
12/08/2013, 13:03
|
#8
|
elite*gold: 0
Join Date: Oct 2013
Posts: 135
Received Thanks: 44
|
Quote:
|
Warum keine Referenzen? Die sind grundsätzlich zu bevorzugen. Damit meine ich deine gesamte Session. Die kannst du ebenfalls Single-Instance-mäßig gestalten, dann muss auch nichts kopiert werden.
|
Schon, aber dann müsste ich die auch irgendwie ordnungsgemäß aus den Containern löschen. Und was passiert wenn die Referenz out of scope läuft?
Außerdem muss ich ja noch die Referenzen in einem Container bekommen, was ja bei noncopyable Objekten problematisch werden kann?
Quote:
Wieso?
Die Frage meine ich ernst, so fit bin ich auch nicht, was die Standard-Container angeht
|
std::set (sortierter Container) eignet sich besser um Inhalte mitten im Container hinzuzufügen oder zu entfernen.
std::vector (unsortierter Container) eignet sich besser zum iterieren der Objekte und oder Objekte am Ende hinzuzufügen oder zu entfernen.
Da dauernd neue Verbindungen hinzukommen oder mitten im Container entfernt werden, gehe ich davon aus das std::set schneller ist. (Ein unsortierter std::vector ist zum suchen sowieso eher ungeeignet)
Was genau dort passiert will ich vorsichtshalber nicht erwähnen, da ich selber nur eine grobe Vorstellung habe.^^
Wann man welchen Container (davon gibt es echt 'nen dutzend  ) verwenden sollte, habe ich aus einer Liste entnommen.
Quote:
|
Um diesen Gedankengang nachvollziehen zu können, müsste man mehr über dein Gesamtdesign wissen. Alleine aus dem Netzwerk-Design erschließt sich das mir jetzt nicht.
|
Das Problem ist hier, dass ich selber noch keine genaue Vorstellungen über das Gesamtdesign gemacht habe. Ich dachte anfangs, dass es sich schon ergeben wird nachdem mein Netzwerk Design steht.
Quote:
Ok, das klingt erstmal sinnig. Je nach Design könnte natürlich auch eine Art Player-Klasse einen Verweis auf die aktive Session haben, die die nötigen Handler in der Session registriert.
Auch hier gilt: Wenn du keinen Grund hast, der explizit für einen Pointer spricht, würde ich eine Referenz nehmen.
|
Könntest du darauf noch etwas eingehen?
Quote:
|
Du könntest auch Funktionsobjekte als Callbacks (ich gehe mal fast davon aus, dass du stinknormale Function-Pointer verwendest; siehe std::function) verwenden, dann kannst du einfach eins registrieren, dass selbst den entsprechenden Account/Character/etc. kennt, dann braucht die Session den nicht zu kennen.
|
Nene, ich verwende schon std::function, über normale Funkionspointer währe mir das zu umständlich.
Die Idee hört sich ziemlich gut an, danke.
Quote:
|
Nunja, da wo Abhängigkeit bestehen muss, da ist sie letztendlich auch unumgänglich und kann nicht Bad Practice sein. Irgendwie muss eine Session nunmal zum Player/Account gehören. In welche Richtung das geht, hängt letztendlich auch vom restlichen Design ab, man kann nicht grundsätzlich einen Weg als falsch darstellen.
|
Da wüsste ich jetzt auch nicht, was ich hinzuzufügen hatte.
Quote:
Originally Posted by Omdihar
Für das mit der Wahl der Standart Container habe ich hier ein schönes Bild
|
Funktioniert leider bei mir nicht.
|
|
|
12/08/2013, 14:24
|
#9
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Quote:
Originally Posted by EasyTale
std::set (sortierter Container) eignet sich besser um Inhalte mitten im Container hinzuzufügen oder zu entfernen.
std::vector (unsortierter Container) eignet sich besser zum iterieren der Objekte und oder Objekte am Ende hinzuzufügen oder zu entfernen.
Da dauernd neue Verbindungen hinzukommen oder mitten im Container entfernt werden, gehe ich davon aus das std::set schneller ist. (Ein unsortierter std::vector ist zum suchen sowieso eher ungeeignet)
Was genau dort passiert will ich vorsichtshalber nicht erwähnen, da ich selber nur eine grobe Vorstellung habe.^^
Wann man welchen Container (davon gibt es echt 'nen dutzend  ) verwenden sollte, habe ich aus einer Liste entnommen.
|
Müssen die Verbindungen sortiert sein? Wenn nicht, könntest du dir std::unordered_set ansehen, das ist im durchschnittlichen Fall besser.
|
|
|
12/08/2013, 15:16
|
#10
|
elite*gold: 0
Join Date: Oct 2013
Posts: 135
Received Thanks: 44
|
Quote:
Originally Posted by Tasiro
Müssen die Verbindungen sortiert sein? Wenn nicht, könntest du dir std::unordered_set ansehen, das ist im durchschnittlichen Fall besser.
|
Quatsch, die müssen nicht sortiert sein, zumindest wüsste ich jetzt selber nicht wofür.
Ich werde es mir aufjedenfall anschauen, danke.
Ich mache mir derzeit noch zuviele Gedanken über das ganze Design.
Mr.Smith hat mir ja zu Referenzen geraten, welche ich auch bevorzugen würde.
Da boost::asio::ip::tcp::socket aber noncopyable ist, sehe ich einige Probleme.
Quote:
Schon, aber dann müsste ich die auch irgendwie ordnungsgemäß aus den Containern löschen. Und was passiert wenn die Referenz out of scope läuft?
Außerdem muss ich ja noch die Referenzen in einem Container bekommen, was ja bei noncopyable Objekten problematisch werden kann?
|
Die stl Container sind darauf ausgelegt, dass der Kontent copyable ist.
Es gibt ja std::reference_wrapper aber das kann nicht die Lösung sein.
|
|
|
 |
Similar Threads
|
20xLv5 Paket/ 20xLv4 Paket ?
10/18/2011 - Nostale - 7 Replies
Es gibt ja das 20xLv5 Paket.
Kann man auch einstellen das man 20xLv4 bekommt ?
Muss man dann 1xLv4 zocken ?
Oder geht das anders ?
|
[B] Youtube Paket (Like + Abo + Klick 1x) [S] 1 e*gold / Paket
07/06/2011 - Social Media Trading - 2 Replies
Hallo E*Pvpers :)
Ich möchte euch hier meinen Youtube dienst anbieten,
1 youtube Paket : Like+Abo+Klick
(lässt sich Variieren (bsp. like+like+abo))
kostet 1 e*gold
Auch könnt ihr bis zu 2 mal diesen dienst in Anspruch nehmen (2 Acc's)
Noch fragen? gleich hier rein mit! Handeln? Link hier reinschreiben!
meine Accountnamen Kriegt ihr per PM zur überprüfung zugeschickt!
(Wegen Schleichwerbung etc.)
|
[Paket]Webspace, Domains, [Paket]
04/29/2010 - elite*gold Trading - 1 Replies
Hallo liebe Community!
Ich biete euch hier Webspace, Domains und Vps's an.
Achtung: Im Moment wird noch kein Elitegold akzeptiert! Es wird erst akzeptiert, wenn ich einen gewissen Vorrat an Paysafekarten habe. Das wird aber nicht lange dauern.
1. Webspace & Domains
Kleines Paket
|
All times are GMT +1. The time now is 06:07.
|
|