[C++] Gameserver - Socketimplementierung

_Grubi

Erfahrenes Mitglied
Hey,

als "der Neue" werfe ich erstmal ein fröhliches "Hallo" in die Runde :)
Ich verfolge schon lange das Geschehen hier und habe mich nun endlich auch einmal registriert, da ich ein paar für mich wichtige Fragen habe.

Dann leg ich auch gleich mal los:
Für ein bekanntes Onlinegame (MMPORG) habe ich mir einen Gameserver in C# (er läuft - jedoch noch nicht optimiert - aber nur mit wenigen Spielern) gebastelt. Da der Server jedoch später mindestens 2000-3000 Spieler gleichzeitig bedienen können soll, habe ich nun vor das ganze nach C++ zu portieren. Im Großen und Ganzen sollte das für mich kein Problem darstellen, jedoch hänge ich momentan an der Socketimplementierung. Ich habe schon ein wenig mit Sockets in C++ rumgespielt, jedoch nicht für solch eine Größenordnung.

Mir stellt sich nun die Frage, wie ich es am geschicktesten aufbauen soll.

1. Möglichkeit

Soll ich es mit Threads lösen? Das würde dann aber bedeuten, dass ich pro Client mindestens 2 Threads habe:
  1. Thread: Abarbeiten der Aufgaben, die für den einzelnen Spieler anstehen, wie z.B. HP/MP (Health-/Manapoints) automatisch auffüllen
  2. Thread: recv()
Wenn ich das in einen Packen würde, würden die allgemeinen Aufgaben solange stehen bleiben, bis was empfangen wurde und die Schleifen durchlaufen könnte
-> Wäre das bei rund 2000-6000 Threads dann nicht etwas zu viel? Da würde der Server doch hoffnungslos zugrunde gehen, oder?

2. Möglichkeit

Arbeiten mit select().
Hier könnte dann das Problem bestehen, dass eine Anfrage zu lange braucht, was dann bedeuten würde, dass bei den anderen Spielern auch nichts mehr geht, da alles blockiert wird.

3. Möglichkeit

Eine Kombination aus Threads & select().
Mehrere Sockets werden in einem Thread zusammengefasst. Dies verringert die ANzahl der benötigten Threads, hat aber immer noch das Problem, dass eventuell der Thread blockiert wird, wenn das ganze etwas zu lange dauert.
Eventuell sollte man es dann so machen, dass der Socket, von dem gelesen werden kann in einen neuen Thread ausgelagert wird und der select-Thread auf den nächsten bereitstehenden Socket warten kann.
-> Könnte es durch das ständige starten und beenden von Threads vielleicht zu Performanceeinbußen kommen? Sollte man eventuell ein paar Threads pausiert starten und denen dann einfach den socket übergeben? Wäre das sinnvoller?

4. Möglichkeit

Die ganzen WSA-Methoden (WSAAsyncSelect und was es da alles gibt).
Mit denen kenn ich mich aber absolut nicht aus. Ich habe bisher auch nicht wirklich viel dazu gefunden. Hauptsächlich nur MSDN Artikel.

Eine Sache noch dazu: Wenn ich bin recv() auf Daten warte, ist es mir dann dennoch möglich an den selben Socket daten zu schicken (aus einem anderen Thread z.B.)?


Das waren mal meine anfänglichen Gedanken. Habt ihr vielleicht noch andere Vorschläge oder könntet mal eure Meinung zu meinen Ideen sagen? Vielleicht hat auch schon jemand Erfahrung mit solchen Dingen gemacht.

Eine weitere Frage die mich noch interessieren würde:
Für welches OS würdet ihr mir das Ganze empfehlen? C# war ja bisher für Windows. Mit C++ hätte ich auch die Möglichkeit auf *nix umzusteigen. Kann man da unter umständen noch etwas Performance herauskratzen?
Oder würdest ihr sogar sagen, dass es egal ist, ob C# oder C++ und ich lieber den bisherigen Server optimieren soll? Man ließ unterschiedliches im bezug auf den Geschwindigkeitsvergleich von C++ und C#.

Ich bedanke mich schonmal,

grubi
 
Zuletzt bearbeitet:
HI,

ich habe mich nun dafür entschieden, es einmal mit der reinen Threadvariante zu probieren, nun stellt sich mir jedoch noch dazu eine Frage, die ich mit SuMa-Benutzung leider auch nicht zufriedenstellend klären konnte:
Gibt es eine Begrenzung der Anzahl an Threads pro Prozess? Hier und da ließt man mal, dass es keine wirkliche Grenze gibt, dann heißt es wieder irgendwas mit 2048...
Kann mir da einer mehr dazu sagen? Nicht, dass das nacher soweit alles fertig ist un dann daran scheitert :-P

Falls das schon als Doppelpost/Pushpost gelten sollte, sorry.
 
Schau mal hier:

1. http://entwickler-forum.de/archive/index.php/t-28913.html
2. http://www.delphipraxis.net/topic79...vcl+mit+exe.html&highlight=portscanner+thread

Zu Link 1: Bei einem Game-Server sieht das natürlich ganz anders aus, klar. Ich habe allerdings auch fremde Anwendungen mit mehr als 50 Threads laufen, soweit meldet mir das mein Taskmanager (Klammergriff -> Ansicht -> Spalten auswählen... -> Häkchen bei Threadanzahl machen) ^^

//PS: Wenn du das mit den Sockets geschafft hast unter c#...könntest du mir dann ein Beispiel schicken? Ich bekomm das nämlich nicht gebacken :P
 
Zuletzt bearbeitet:
Danke für die Links, ich schau gleich mal rein.

Zu C#: Ich habe das mit asyncronen Sockets gemacht (BeginReceive, EndReceive, BeginSend, EndSend + AsyncCallback). Ich Such dir nacher mal die betreffenden Dateien raus und verpack sie dir.
 
Okay, danke. Wollte nämlich mal ein Multi-Player Kartenspiel schreiben, hab die Sockets gesehen, und habs dann wieder sein gelassen, weil ich das zusammen gesuchte nicht wirklich verstanden habe, weils sehr zusammengewürfelt war.

Ich denke, deinen Code werd ich dann auch vertehen, ist ja dann alles in einem ^^
 
Deine Links haben mir einen schönen Weg gezeigt: Threadpools. Da muss ich mich mal richtig einlesen. Das scheint brauchbar zu sein :-P

PM is übrigends raus.
 
Zuletzt bearbeitet:
Nachdem ich die Links noch etwas weiter studiert habe, bin ich über etwas gestolpert, dass ich nun auch verwende. Das Ganze nennt sich "Completion Ports". Falls also jemand mal unter Windows eine Socket-Anwendung mit vielen Verbindungen erstellen will, der sollte sich das zu gemüte führen (Suche nach "C++ IOCP").
Danke, WorldRacer, für den, wahrscheinlich unbewussten, guten Hinweis :)

Damit hat sich das für mich erst einmal erledigt.
 
Zurück