Hellblazer
Lt. Commander
- Registriert
- Aug. 2011
- Beiträge
- 1.604
Hallo,
ich bin gerade dabei in C# einen TCP-Server zu programmieren. Der Server basiert auf SocketAsyncEventArgs.
Der Code für den Server ist im Grunde schon vorhanden (senden, empfangen und Unterscheidung der Clients funktioniert). Ich zerbreche mir gerade nur den Kopf über ein Kommunikationsprotokoll.
Das Grundgerüst des Servers soll variabel einsetzbar sein. Ob darüber eine Chat-Anwendung, ein Spiel oder Datenübertragung laufen soll, soll frei wählbar sein.
Deshalb dachte ich mir, dass ich verschiedene Schichten einführe. Die unterste Schicht ist das Servergrundgerüst. Darauf lässt sich eine beliebige weitere Schicht, die eine genauere Kommunikationsprotokolldefinition enthält, aufsetzen.
Das heißt also, dass das Grundgerüst von einer höheren Schicht Daten/Pakete erhält und diese dann entsprechend versendet.
Das Grundgerüst weiß dabei nichts von irgendeinem Kommunikationsprotokoll, sondern sendet/epfängt die Daten einfach nur.
Das einzige das die unterste Schicht mit den Daten macht, ist ein Längenprefix voranzustellen, das die Länge der Daten enthält, damit der Client weiß, wann alle Daten eines Pakets erhalten wurden. Der Prefix ist einfach ein Integer der die Paketgröße enthält in Bytes umgewandelt. Das sieht dann in etwa so aus:
Jetzt bin ich gerade am überlegen, wie ich am geschicktesten ein Kommunikationsprotokoll für die höhere Schicht implementiere. Mein Ziel ist es, verschiedene Kommandos zu haben, die dann auf dem Server/Client die entsprechend Vorgänge einleiten. Mir schwirren da gerade verschiedene Ansätze im Kopf herum:
1. Textbasierte Kommandos mit mehreren Kommandos pro Paket
Ein Paket enthält eine Kombination aus Befehlen, die zusammen eine abgeschlossene Handlung darstellen.
Nachteil: Kommandos als String verbrauchen relativ viel Speicher
Zum Beispiel sendet ein Nutzer in einem Chat eine Nachricht an einen anderen Nutzer
Aufbau: Kommando1:Nutzdaten zum Kommando1; Kommando2:Nutzdaten zu Kommando2...
Beispiel: cmdSAY:Hello;cmdToUser:TestUser
2. Textbasierte Kommandos mit nur einem Kommando pro Paket:
Wie 1., nur dass jedes Paket genau ein Kommando enthält. Führt möglicherweise zu vielen Sende-Aufrufen im Client und die Pakete müssen im Server wieder zusammengesetzt werden, man muss sich aber nicht um die Länge der Nutzdaten eines jeden Kommandos kümmern
Aufbau: Paket1: Kommando1:Nutzdaten zum Kommando1 Paket2:Kommando2:Nutzdaten zu Kommando2...
Beispiel: Paket1: cmdSAY:Hello; Paket2: cmdToUser:TestUser
3. Byte basierte Kommandos
Es wird in der Nachricht ein Byte reserviert, dessen Bits die Kommandos repräsentieren. Vorteil: Es lassen sich mit einem Byte relativ viele Kommandos (256) darstellen.
Aufbau: ByteKommando:Nutzdaten;
Methode 3. könnte dann auch wie Methode 2. ausgeführt werden (pro Paket nur ein Kommando). Da weiß ich nicht was besser ist. Ein Kommando pro Paket endet in vielen Sendeaufrufen. Dafür sind die Pakete klein, müssen aber beim Empfänger wieder zusammengesetzt werden bzw. nacheinander durchlaufen werden zum abarbeiten. Je nachdem wie schnell die Sendevorgänge laufen kommen die einzelnen Pakete sowieso im selben Buffer am Server an und dann müsste extra der Buffer in die einzelnen Pakete gesplittet werden.
Grundsätzlich sollte eine Paket etwa so aussehen:
Die Länge wird von der untersten Schicht hinzugefügt. Alles danach kommt aus einer höheren Schicht.
Meine Ziele sind:
- möglichst schnell beim Parsen der Pakete
- möglichst schnell beim erstellen der Pakete
- Erweiterbarkeit
- Stabilität
- Speicher schonend
Da die unterste Schicht sowieso nur bytes versendet würde ich zu Methode 3 tendieren. Da müssen dann nur noch die Nutzdaten zu bytes konvertiert werden. Die Kommandos sind dann schon in passender Form. Ein weiteres Problem wäre die Feststellung der Länge der Nutzdaten nach jedem Kommando. Da könnte man dann nach jedem Kommando noch 2 weitere Bytes setzen, die die Länge der folgenden Nutzdaten beinhaltet.
Hat jemand eine Idee, wie ich ein Kommunikationsprotokoll, dass meine oben genannten Ziele erfüllt am geschicktesten umsetzen kann?
ich bin gerade dabei in C# einen TCP-Server zu programmieren. Der Server basiert auf SocketAsyncEventArgs.
Der Code für den Server ist im Grunde schon vorhanden (senden, empfangen und Unterscheidung der Clients funktioniert). Ich zerbreche mir gerade nur den Kopf über ein Kommunikationsprotokoll.
Das Grundgerüst des Servers soll variabel einsetzbar sein. Ob darüber eine Chat-Anwendung, ein Spiel oder Datenübertragung laufen soll, soll frei wählbar sein.
Deshalb dachte ich mir, dass ich verschiedene Schichten einführe. Die unterste Schicht ist das Servergrundgerüst. Darauf lässt sich eine beliebige weitere Schicht, die eine genauere Kommunikationsprotokolldefinition enthält, aufsetzen.
Das heißt also, dass das Grundgerüst von einer höheren Schicht Daten/Pakete erhält und diese dann entsprechend versendet.
Das Grundgerüst weiß dabei nichts von irgendeinem Kommunikationsprotokoll, sondern sendet/epfängt die Daten einfach nur.
Das einzige das die unterste Schicht mit den Daten macht, ist ein Längenprefix voranzustellen, das die Länge der Daten enthält, damit der Client weiß, wann alle Daten eines Pakets erhalten wurden. Der Prefix ist einfach ein Integer der die Paketgröße enthält in Bytes umgewandelt. Das sieht dann in etwa so aus:
Längenprefix|beliebige weitere Daten der höher liegenden Schicht...
Jetzt bin ich gerade am überlegen, wie ich am geschicktesten ein Kommunikationsprotokoll für die höhere Schicht implementiere. Mein Ziel ist es, verschiedene Kommandos zu haben, die dann auf dem Server/Client die entsprechend Vorgänge einleiten. Mir schwirren da gerade verschiedene Ansätze im Kopf herum:
1. Textbasierte Kommandos mit mehreren Kommandos pro Paket
Ein Paket enthält eine Kombination aus Befehlen, die zusammen eine abgeschlossene Handlung darstellen.
Nachteil: Kommandos als String verbrauchen relativ viel Speicher
Zum Beispiel sendet ein Nutzer in einem Chat eine Nachricht an einen anderen Nutzer
Aufbau: Kommando1:Nutzdaten zum Kommando1; Kommando2:Nutzdaten zu Kommando2...
Beispiel: cmdSAY:Hello;cmdToUser:TestUser
2. Textbasierte Kommandos mit nur einem Kommando pro Paket:
Wie 1., nur dass jedes Paket genau ein Kommando enthält. Führt möglicherweise zu vielen Sende-Aufrufen im Client und die Pakete müssen im Server wieder zusammengesetzt werden, man muss sich aber nicht um die Länge der Nutzdaten eines jeden Kommandos kümmern
Aufbau: Paket1: Kommando1:Nutzdaten zum Kommando1 Paket2:Kommando2:Nutzdaten zu Kommando2...
Beispiel: Paket1: cmdSAY:Hello; Paket2: cmdToUser:TestUser
3. Byte basierte Kommandos
Es wird in der Nachricht ein Byte reserviert, dessen Bits die Kommandos repräsentieren. Vorteil: Es lassen sich mit einem Byte relativ viele Kommandos (256) darstellen.
Aufbau: ByteKommando:Nutzdaten;
Methode 3. könnte dann auch wie Methode 2. ausgeführt werden (pro Paket nur ein Kommando). Da weiß ich nicht was besser ist. Ein Kommando pro Paket endet in vielen Sendeaufrufen. Dafür sind die Pakete klein, müssen aber beim Empfänger wieder zusammengesetzt werden bzw. nacheinander durchlaufen werden zum abarbeiten. Je nachdem wie schnell die Sendevorgänge laufen kommen die einzelnen Pakete sowieso im selben Buffer am Server an und dann müsste extra der Buffer in die einzelnen Pakete gesplittet werden.
Grundsätzlich sollte eine Paket etwa so aussehen:
Länge|Version|Typ|beliebige Kommandos u. Nutzdaten
Die Länge wird von der untersten Schicht hinzugefügt. Alles danach kommt aus einer höheren Schicht.
Meine Ziele sind:
- möglichst schnell beim Parsen der Pakete
- möglichst schnell beim erstellen der Pakete
- Erweiterbarkeit
- Stabilität
- Speicher schonend
Da die unterste Schicht sowieso nur bytes versendet würde ich zu Methode 3 tendieren. Da müssen dann nur noch die Nutzdaten zu bytes konvertiert werden. Die Kommandos sind dann schon in passender Form. Ein weiteres Problem wäre die Feststellung der Länge der Nutzdaten nach jedem Kommando. Da könnte man dann nach jedem Kommando noch 2 weitere Bytes setzen, die die Länge der folgenden Nutzdaten beinhaltet.
Hat jemand eine Idee, wie ich ein Kommunikationsprotokoll, dass meine oben genannten Ziele erfüllt am geschicktesten umsetzen kann?
Zuletzt bearbeitet: