Frage

Ich versuche, ein besseres Verständnis von TCP / IP-Sockets in c # zu gewinnen, wie ich mich selbst herauszufordern will zu sehen, ob ich eine Arbeits MMO-Infrastruktur schaffen (Spielwelt, Karte, Spieler, usw.) rein für pädagogische Zwecke als ich habe nicht die Absicht, ein anderes jener zu sein „OMGZ iz werde meine r0x0r MMORPG machen, dass als WoW besser sein wird !!!“, Sie wissen, was im reden.

Wie auch immer, ich habe mich gefragt, ob jemand etwas Licht, wie Schuppen kann, wie man Ansatz könnte diese Art von System entwerfen und welche Arten von Dingen erforderlich sind, und was sollte ich achten?

Meine ursprüngliche Idee war, um das System in separate Client / Server-Verbindungen mit jeder Verbindung zu brechen (auf einem eigenen Hafen) eine bestimmte Aufgabe, wie die Aktualisierung von Spielern / Monster Positionen durchführt, das Senden und Empfangen von Chat-Nachrichten, usw., die zu mich würde die Verarbeitung der Daten einfacher, weil man nicht immer müssten einen Header auf die Daten setzen zu wissen, welche Informationen das Paket enthält.

Ist das sinnvoll und nützlich ist oder bin ich nur Art und Weise über die Dinge zu verkomplizieren?

Ihre Antworten werden sehr geschätzt.

War es hilfreich?

Lösung

Wenn Sie Socket-Level-Programmierung tun, dann unabhängig davon, wie viele Ports, die Sie für jeden Nachrichtentyp zu öffnen, benötigen Sie noch einen Header irgendeiner Art haben. Auch wenn es nur die Länge des Restes der Nachricht. Having said, dass es leicht ist, eine einfache Kopf- und Schwanz-Struktur auf eine Nachricht hinzuzufügen. Ich würde denken, es ist einfacher, nur mit einem Port auf der Clientseite zu tun haben.

Ich glaube, die modernen MMORPGs (und vielleicht sogar die alten) hatten zwei Ebenen von Servern. Der Login-Server, die Sie als zahlender Kunde überprüfen. Nach der Überprüfung diese passieren Sie aus dem Spiel-Server, der die ganze Spielwelt Informationen enthalten. Trotzdem nur diese immer noch den Client benötigt eine Steckdose offen zu haben, aber nicht verbieten nicht mehr.

Zusätzlich meisten MMORPGs verschlüsseln auch alle ihre Daten. Wenn Sie dies als eine Übung für Spaß schreiben, dann wird dies nicht so sehr wichtig.

Für die Gestaltung / Schreiben Protokolle im Allgemeinen hier sind die Dinge, die ich befürchten:

Endianess

Sind die Client und Server stets garantiert die gleiche Endianess haben. Wenn nicht muss ich das in meinem Serialisierungscode behandeln. Es gibt mehrere Möglichkeiten Endianess zu behandeln.

  1. Ignorieren Sie es - offensichtlich eine schlechte Wahl
  2. Geben Sie die endianness des Protokolls. Dies ist, was die älteren Protokolle did / tun daher der Begriff Netzwerk, um die immer Big-Endian war. Es ist nicht wirklich wichtig, die Sie angeben Endianess nur, dass Sie den einen oder anderen angeben. Einige krustige alte Netzwerk-Programmierer in die Arme, wenn man keine großen Endianess verwenden, aber wenn Sie Ihre Server und die meisten Kunden Little-Endian sind wirklich Sie kaufen nicht selbst etwas anderes als zusätzliche Arbeit durch das Protokoll Big-Endian zu machen.
  3. Markieren Sie die Endianess in jedem Kopf - Sie können ein Cookie hinzufügen, die Ihnen die Endianess des Client / Server wird zeigen, und jede Nachricht wird entsprechend umgerechnet lassen werden je nach Bedarf. Zusätzliche Arbeit!
  4. Sie Ihr Protokoll Agnostiker -. Wenn Sie alles als ASCII-Strings senden, dann Endianess ist irrelevant, aber auch viel mehr ineffizient

Von den 4 würde ich in der Regel 2, auswählen und den Endianess angeben, dass die Mehrheit der Kunden zu sein, die nun Tage Little-Endian sein.

Vorwärts und Rückwärtskompatibilität

Ist das Protokoll müssen vorwärts und rückwärts kompatibel sein. Die Antwort sollte fast immer ja sein. In diesem Fall wird dies bestimmt, wie ich das Design über alle Protokolle in Bezug auf der Versionierung und wie jede einzelne Nachricht erstellt kleinere Änderungen zu handhaben, die nicht wirklich Teil der Versionierung sein sollten. Sie können auf diese Punt und XML verwenden, aber Sie viel Effizienz verlieren.

Für das Gesamt Versionierung ich in der Regel etwas einfacher gestalten. Der Client sendet eine Versionierung Nachricht angeben, dass es Version X.Y spricht, solange der Server diese Version unterstützen kann es sendet eine Nachricht, die die Version des Clients und alles geht nach vorn Anerkennung zurück. Ansonsten nacks es den Client und beendet die Verbindung.

Für jede Nachricht, die Sie so etwas wie die folgenden haben:

+-------------------------+-------------------+-----------------+------------------------+
| Length of Msg (4 bytes) | MsgType (2 bytes) | Flags (4 bytes) | Msg (length - 6 bytes) |
+-------------------------+-------------------+-----------------+------------------------+

Die Länge erzählt offensichtlich, wie lange die Nachricht, ohne die Länge selbst. Die MsgType ist die Art der Nachricht. Nur zwei Bytes für diesen, da 65356 ist vielen Nachrichtentyp für Anwendungen. Die Flaggen sind dort, damit Sie wissen, was in der Nachricht serialisiert wird. Dieses Feld wird mit der Länge kombiniert ist, was Sie vorwärts und rückwärts Kompatibilität gibt.

const uint32_t FLAG_0  = (1 << 0);
const uint32_t FLAG_1  = (1 << 1);
const uint32_t FLAG_2  = (1 << 2);
...
const uint32_t RESERVED_32 = (1 << 31);

Dann wird Ihr Deserialisierung-Code kann in etwa wie folgt tun:

uint32 length = MessageBuffer.ReadUint32();
uint32 start = MessageBuffer.CurrentOffset();
uint16 msgType = MessageBuffer.ReadUint16();
uint32 flags = MessageBuffer.ReadUint32();

if (flags & FLAG_0)
{
    // Read out whatever FLAG_0 represents.
    // Single or multiple fields
}
// ...
// read out the other flags
// ...

MessageBuffer.AdvanceToOffset(start + length);

Auf diese Weise können Sie auf Hinzufügen neue Felder bis zum Ende der Nachrichten, ohne das gesamte Protokoll zur Revision hat. Es stellt auch sicher, dass alte Server und Clients Flags ignorieren sie nicht kennen. Wenn sie die neuen Fahnen und Felder verwenden müssen, dann Simpl Siey die Version Gesamt-Protokoll ändern.

Verwenden Sie einen Frame Work oder nicht

Es gibt verschiedene Netzwerk-Frameworks ich für eine Business-Anwendung in Betracht ziehen würden. Es sei denn, ich einen besonderen Bedarf zu kratzen hätte, würde ich mit einem Standard-Rahmen hinausgehen. In Ihrem Fall sollten Sie Socket-Level-Programmierung erlernen, so ist dies eine Frage bereits für Sie beantwortet.

Wenn man tut, verwenden Sie einen Rahmen stellen Sie sicher, es befasst sich mit den beiden Anliegen oben, oder zumindest wird nicht in die Quere, wenn Sie es in diesen Bereichen anpassen müssen.

Bin ich mit einem Dritten zu tun

In vielen Fällen können Sie mit einem Dritten Server / Client Sie müssen mit kommunizieren zu tun haben. Dies bedeutet, einige Szenarien:

  • Sie bereits ein Protokoll definiert haben - einfach ihr Protokoll verwenden
  • .
  • Sie haben bereits ein Protokoll definiert (und sie sind bereit, es zu benutzen) - wieder einfache Verwendung der definierten Protokoll
  • Sie verwenden einen Standard-Framework (WSDL basierte, usw.) - den Rahmen verwenden
  • .
  • hat Keine Partei ein Protokoll definiert - Versuchen Sie, die beste Lösung für alle Faktoren bei der Hand (alle die, die ich hier erwähnt), sowie deren Niveau competencey (zumindest so weit wie Sie sagen können) bis determing. stellen Sie sicher, ungeachtet beide Seiten vereinbaren und zu verstehen, das Protokoll. Aus Erfahrung kann dies schmerzhaft oder angenehm sein. Es hängt davon ab, wen Sie arbeiten.

In jedem Fall werden Sie nicht mit einer dritten Partei arbeiten werden, so dass dies wirklich nur der Vollständigkeit halber hinzugefügt.

Ich fühle mich, als ob ich viel mehr darüber schreiben könnte, aber es ist schon ziemlich lange. Ich hoffe, das hilft und wenn Sie spezielle Fragen haben, fragen Sie einfach auf Stackoverflow.

Ein Bearbeitungs knoopx Frage zu beantworten:

Andere Tipps

Ich glaube, Sie kriechen müssen, bevor Sie gehen und bevor Sie laufen. Zuerst sollten Sie das Design des Rahmens und Verbindungen Recht, Sorgen dann über die Skalierbarkeit. Wenn Ihr Ziel ist C # und TCP / IP-Programmierung zu erlernen, dann machen Sie nicht diese härter an sich selbst.

Gehen Sie weiter mit Ihren ersten Gedanken und halten die Daten getrennte Ströme.

hat Spaß und viel Glück

würde ich gegen mehrere Verbindungen für die verschiedenen Informationen beraten. Ich würde einige Protokolle entwerfen, die ein Header mit Informationen enthalten verarbeitet werden. Verwenden Sie so wenig Ressourcen wie möglich. Auch Sie können nicht Updates wollen vom Client zum Server für verschiedene Positionen und Statistiken senden. Ansonsten können Sie in eine Situation kommen, wo ein Benutzer ihre Daten ändern können zurück an den Server gesendet.

Sprich ein Benutzer eines Monsters Standort fälscht Vergangenheit etwas zu bekommen. Ich würde nur der Positionsvektor des Benutzers aktualisieren und Aktionen. Lassen Sie werden den Rest der Informationen verarbeitet und validiert durch den Server.

Ja, ich glaube, du hast Recht über die einzige Verbindung, und natürlich würde nicht der Client mit dem Server alle aktuellen Daten aussenden, mehr wie nur einfache Befehle wie ‚vorwärts‘, ‚links abbiegen‘, usw., und die Server würde das Zeichen auf der Karte bewegen und die neuen Koordinaten zurück an den Client senden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top