2017-07-06 7 views
2

Zunächst einmal möchte ich mich für irgendwelche dummen Fragen entschuldigen, ich lerne immer noch Netzwerkprogrammierung.Best Practice für Java UDP Multithreading

Ich habe nie viel Netzwerkprogrammierung gemacht, außer aus eigenem Interesse, und ich habe nur Javas Socket- und ServerSocket-Klassen verwendet. Bei diesen Klassen verwendeten die Paradigmen, die ich verwendete, einen einzelnen Java-Thread auf der Serverseite, der Verbindungen von Clients akzeptierte und diesen akzeptierten Socket dann an seinen eigenen Thread weitergab. Bei 100 gleichzeitigen Clients wären also (potentiell) 100 Threads vorhanden. Dann könnten der Client und der Server auf ihren eigenen Threads miteinander kommunizieren, getrennt von den anderen Komponenten des Systems.

Jetzt geben Sie den DatagramSocket ... Ich lerne gerade über TCP vs UDP, also gerade diese Klasse entdeckt. Es macht Sinn ... Sie hören auf Pakete an einem Port und senden Pakete über einen Port/eine Adresse. Der Körper enthält eine bestimmte Anzahl von Bytes und ist optional (Immer noch lernen, was die maximalen Körpergrößen sind und so). Aus den Online-Informationen habe ich erfahren, dass der Socket nach ANY-Paketen an diesem Port lauscht und die Quelle aus den Paket-Headern ableitet.

Das ist alles gut und gut, und ich bin komfortabel mit der Weiterleitung dieser Pakete an ihre eigenen Runnables in einem Pool, oder ihre eigenen Threads, etc. Was mich stört ist, dass mit TCP-Sockets jeder Thread (One of die 100 im obigen Beispiel) empfangen nur Nachrichten von der entsprechenden Quelle. Bei Datagram-Sockets gehen alle Pakete von jedem Client zu einem einzelnen Thread ... und dieser Thread ist dafür verantwortlich, die Arbeit zu teilen.

Wie würde so etwas in einem MMO-Spiel funktionieren ... sagen Sie, Sie haben einen Spielserver, der 5000 Spieler unterstützt und jeder Spieler 15 Pakete pro Sekunde ... Das sind 75.000 Pakete pro Sekunde, was für eine Single schwer scheint Thread zu behandeln. (Im Gegensatz zu 5000 Threads, die jeweils 15 pro Sekunde haben könnten). Offensichtlich könnte ein Thread die Pakete basierend auf Paketheadern und einem Client hashmap an die richtigen Stellen weiterleiten, aber ich bin nur unbehaglich, dass der Zuhörer-Thread selbst diese Logik ausführt.

Jetzt ist es möglich, dass TCP etwas Ähnliches tut (Ein Paket-Listener-Thread, der die Daten an den entsprechenden Socket weiterleitet), also verliere ich wirklich nichts. Ich schätze, die Wurzelfrage läuft auf ... Ist es möglich, mehrere Server-Threads den gleichen Port zu hören? Ich stelle mir zum Beispiel einen Load-Balancer vor, der die Pakete an verschiedene DataGramSocket-Listener round rockt (Eins für jeden Thread, vielleicht 3-4 Threads). Dann können diese Listener die Aufgabe des ursprünglichen einzelnen Threads übernehmen, der diese ungeordneten Pakete an die richtigen Stellen im Programm sendet (Beispiel, dieses Paket kam von 123.456.789.123 auf Port 6750 ... lasst uns unsere clientMap nachsehen, wo das hinführen sollte Geh ... Okay, sende an diese Thread-Paket-Warteschlange).

Ich denke die Antwort ist, dass solange der Thread alle Client-Pakete ist sehr leicht (nur Paket empfangen, delegieren, wiederholen), dann gibt es kein Problem, auch für hohe Datenaufkommen.

Danke!

EDIT: Nach einigem Nachdenken und Am_I_Helpful's Kommentar (Und jetzt Jamal H), realisierte ich, dass Sie dies auf einer Maschinen- oder Portebene abstrahieren können. Wenn Sie also 3000 Spieler haben, könnten Sie einen Load Balancer haben, der diesen Spieler zu einer bestimmten Maschine oder sogar zu einem bestimmten Port auf dem Rechner lenkt. Auf diese Weise können Sie X Anzahl von Server-Threads haben, die jeweils auf Pakete auf einem anderen Port warten. Spieler 1 kann den Port 7712 erreichen, Spieler 2 kann den Wert 7713 erreichen.

+0

Sie haben immer verteilte Architektur für solche massive Architektur! Und UDP ist verbindungslos und schnell im Vergleich zu TCP. Außerdem sind die in Spielen ausgetauschten Pakete gewöhnlich leichtgewichtig. –

+0

Ahh guter Punkt! Also welcher Server das Paket bekommt, könnte anders sein. Ich dachte Thread-Ebene, nicht Maschinen-Ebene. Könnte sogar Port-Ebene auf dem gleichen Computer gehen, vorausgesetzt, es war sehr groß (wie 16 Kerne, 64 GB Speicher). Dann könnten Sie einen Thread für jeden Port haben, den Sie gerade abhielten. Einem bestimmten "Spieler" könnte ein bestimmter Port zugewiesen werden. – user2770791

Antwort

0

Wenn Sie keinen Zugriff auf ein großes Team haben, würden Sie nicht den gesamten Netzwerkcode von Grund auf für ein MMO schreiben .Sie würden eine Art von Netzwerkframework verwenden, das Lastenausgleich und Threading für Sie handhabt (netty ist ein gutes für Java)

Für ein MMO würden Sie Non Blocking IO (NIO) verwenden, die nicht die Anforderung jedes Clients abbildet zu seinem eigenen Thread, aber stattdessen hat eine bestimmte Anzahl von Threads, die es verwenden will (bestimmt durch die Anzahl der Kerne), und behandelt es so

In Bezug auf das Laden jeder Anfrage auf einem einzigen Thread gibt es ein paar Optionen. Dies ist der Grund, warum MMOs mehrere Server haben, jeder für einen anderen Bereich in einem Spiel. Der zentrale Server würde dem Spieler die IP und den Port des Bereichs-Servers geben, in dem er sich gerade befindet. Sie können auch mehrere Ports auf einem einzelnen Server akzeptieren, wenn der Server leistungsfähig ist, und einfach verschiedene Player an verschiedene Ports senden, wenn Sie möchten wollte die Last über mehrere Threads balancieren

+0

Gute Punkte, danke für die Antwort! Ich habe nicht daran gedacht, dass ein Server sein eigenes Gebiet der Welt abwickelt. Das würde ziemlich viel Sinn machen, warum es in World of Warcraft zum Beispiel eine signifikante Ladezeit zwischen den zwei Hälften der Welt gab - ich wurde wahrscheinlich auf eine andere Maschine gesetzt! – user2770791

+0

@ user2770791 Genau so sind WOW und die meisten anderen MMOs strukturiert –