16 Stimmen

Objektorientierte Vernetzung

Ich habe eine Reihe von Netzwerksystemen geschrieben und habe eine gute Vorstellung davon, wie Netzwerke funktionieren. Am Ende habe ich jedoch immer eine Funktion zum Empfangen von Paketen, die eine riesige Switch-Anweisung ist. Das fängt an, mich zu nerven. Ich hätte viel lieber eine schöne, elegante, objektorientierte Lösung für den Empfang von Paketen, aber jedes Mal, wenn ich versuche, eine gute Lösung zu finden, komme ich nicht weiter.

Nehmen wir zum Beispiel an, Sie haben einen Netzwerkserver. Er wartet dort einfach auf Antworten. Ein Paket kommt herein und der Server muss das Paket validieren und dann entscheiden, wie es zu behandeln ist.

Im Moment mache ich das, indem ich die Paket-ID im Header einschalte und dann einen riesigen Haufen von Funktionsaufrufen habe, die jeden Pakettyp behandeln. Bei komplizierten Netzwerksystemen führt dies zu einer monolithischen Switch-Anweisung, und ich mag es wirklich nicht, auf diese Weise zu arbeiten. Eine Möglichkeit, die ich in Betracht gezogen habe, ist die Verwendung einer Map von Handler-Klassen. Ich kann dann das Paket an die entsprechende Klasse übergeben und die eingehenden Daten verarbeiten. Das Problem, das ich damit habe, ist, dass ich eine Möglichkeit brauche, jeden Paket-Handler mit der Map zu "registrieren". Das bedeutet im Allgemeinen, dass ich eine statische Kopie der Klasse erstellen muss und diese dann im Konstruktor mit dem zentralen Packet-Handler registrieren muss. Während dies funktioniert, scheint es wirklich wie eine unelegante und fiddly Weise der Handhabung.

Editar : Es wäre ideal, ein System zu haben, das in beide Richtungen funktioniert, d.h. eine Klassenstruktur, die das Senden und Empfangen der gleichen Pakettypen leicht handhabt (natürlich mit unterschiedlichen Funktionen).

Kann mir jemand einen besseren Weg zur Behandlung eingehender Pakete zeigen? Links und nützliche Informationen sind sehr willkommen!

Ich bitte um Entschuldigung, wenn ich mein Problem nicht gut beschrieben habe, denn meine Unfähigkeit, es gut zu beschreiben, ist auch der Grund dafür, dass es mir nie gelungen ist, eine Lösung zu finden.

5voto

ssmir Punkte 1512

Zur Handhabung des Pakettyps: Für mich ist die Karte die beste Lösung. Allerdings würde ich ein einfaches Array (oder einen Vektor) anstelle einer Karte verwenden. Es würde die Zugriffszeit konstant machen, wenn Sie Ihre Pakettypen sequentiell von 0 aufzählen.

Was die Klassenstruktur betrifft. Es gibt Bibliotheken, die diese Aufgabe bereits übernehmen: Verfügbare Sprachen zur Definition von Spielenetzwerkprotokollen und Codegenerierung . z.B. Googles Protokollpuffer scheint vielversprechend zu sein. Es erzeugt eine Speicherklasse mit Gettern, Settern, Serialisierungs- und Deserialisierungsroutinen für jede Nachricht in der Protokollbeschreibung. Die Protokollbeschreibungssprache sieht mehr oder weniger umfangreich aus.

1voto

Blrfl Punkte 6637

Eine Karte von Handler-Instanzen ist so ziemlich der beste Weg, damit umzugehen. Daran ist nichts unelegantes.

1voto

Thomas Matthews Punkte 54757

Meiner Erfahrung nach ist das tabellengesteuerte Parsing die effizienteste Methode.

Obwohl std::map schön ist, verwende ich am Ende statische Tabellen. Die std::map kann nicht statisch als konstante Tabelle initialisiert werden. Sie muss während der Laufzeit geladen werden. Tabellen (Arrays von Strukturen) können als Daten deklariert und zur Kompilierzeit initialisiert werden. Ich bin noch nicht auf Tabellen gestoßen, die so groß sind, dass eine lineare Suche einen Engpass darstellt. Normalerweise ist die Tabellengröße so klein, dass der Overhead bei einer binären Suche langsamer ist als bei einer linearen Suche.

Um die Leistung zu erhöhen, verwende ich die Nachrichtendaten als Index in der Tabelle.

1voto

ulidtko Punkte 13601

Wenn Sie OOP machen, versuchen Sie, jedes Ding als Objekt darzustellen, richtig? Also werden auch Ihre Protokollnachrichten zu Objekten; Sie werden wahrscheinlich eine Basisklasse haben YourProtocolMessageBase die das Verhalten jeder Nachricht kapseln wird und von der Sie Ihre polymorph spezialisierten Nachrichten erben werden. Dann brauchen Sie nur noch einen Weg, um jede Nachricht (d.h. jede YourProtocolMessageBase Instanz) in eine Byte-Zeichenkette umzuwandeln, und eine Möglichkeit, dies umgekehrt zu tun. Solche Methoden werden als Serialisierung Techniken; einige auf Metaprogrammierung basierende Implementierungen existieren.

Schnelles Beispiel in Python:

from socket import *
sock = socket(AF_INET6, SOCK_STREAM)
sock.bind(("localhost", 1234))
rsock, addr = sock.accept()

Server blockiert, starten Sie eine weitere Instanz für einen Client:

from socket import *
clientsock = socket(AF_INET6, SOCK_STREAM)
clientsock.connect(("localhost", 1234))

Verwenden Sie nun das in Python integrierte Serialisierungsmodul, pickle Kunde:

import pickle
obj = {1: "test", 2: 138, 3: ("foo", "bar")}
clientsock.send(pickle.dumps(obj))

Server:

>>> import pickle
>>> r = pickle.loads(rsock.recv(1000))
>>> r
{1: 'test', 2: 138, 3: ('foo', 'bar')}

Wie Sie also sehen können, habe ich gerade über link-local eine Python Objekt . Ist das nicht OOP?

Ich denke, die einzig mögliche Alternative zur Serialisierung ist die Beibehaltung der Bimap IDs Klassen. Das sieht wirklich unvermeidlich aus.

1voto

umlcat Punkte 3993

Sie wollen weiterhin das gleiche Paketnetzwerkprotokoll verwenden, aber es in ein Objekt in der Programmierung übersetzen, richtig?

Es gibt mehrere Protokolle, die es Ihnen ermöglichen, Daten als Programmierobjekte zu behandeln, aber es scheint, dass Sie nicht das Protokoll ändern wollen, sondern nur die Art und Weise, wie es in Ihrer Anwendung behandelt wird.

Enthalten die Pakete so etwas wie ein "Tag" oder Metadaten oder eine "ID" oder einen "Datentyp", der eine Zuordnung zu einer bestimmten Objektklasse ermöglicht? Wenn ja, können Sie ein Array erstellen, das die ID und die passende Klasse speichert, und ein Objekt erzeugen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X