XML-Stream
-
hallo,
ich wollte ein kleines Protokoll auf XML-Basis basteln und stoß beim Planen schon auf ein Problem, welches ich nicht auf anhieb lösen kann. Jedes XML-Dokument hat ja eine Root-Node. Wenn jetzt die Daten über eine Netzwerkverbindung reinkommen muss ich ja erstmal alles in einen Buffer schreiben. Anschließend muss ich ja die Root-Nodes auseinander bekommen um sie zu parsen - es kann ja sein, dass nicht nur eine Root-Node im Buffer vorhanden ist. Hat jemand soetwas schon gemacht oder einen Lösungsansatz? Ich hab mir auch schon einige Jabber-Projekte angeschaut (das Protokoll läuft ja schließlich auch mit XML) aber leider sind die meist einfach zu komplex. Ich benutze die libxml2 zum parsen.
mfg blan
-
Du könntest den Wurzelknoten implizit machen.
-
Mach doch entweder 1 Wurzelknoten/Verbindung oder 1 Wurzelknoten/Paket, dann weißt du bei jedem neuen Wurzelknoten hast du ein neues Paket
btw. nimmt man nicht für so was SAX und parst die Daten, wie sie ankommen?
btw. XML ist für Netzwerkprotokolle nicht wirklich ideal!
-
okay, mit einem Wurzelknoten wäre das wie bei jabber - das ist nicht schlecht. Dann parst SAX also auch nur wenn eine Node komplett ist oder? Ansonsten würde es ein Problem geben, wenn eine Node nur zur hälfte übertragen wäre und schon geparst würde?
warum ist es denn schlecht für die Kommunikation von zwei Programmen XML als Basis zu nehmen - Jabber macht das doch auch. Außerdem ehöht es doch das Verstädnis des Protokolls?
mfg blan
-
Nö. Der einzige Vorteil an XML in diesem Zusammenhang ist die extrem leichte Erweiterbarkeit. Ansonsten produziert das größtenteils Müll, der nicht sein muss (sowohl im Programm als auch im Netzwerk).
Aber es kommt natürlich stark darauf an, was du mit dem Protokoll vorhast.
-
okay, dann werde ich wohl auf ein Byte-Protokoll setzen. ich hab mir das jetzt so vorgestellt:
ich habe eine Header mit ein paar Informationen über das Paket und die Daten (evtl. noch eine Prüfsumme). Die Länge der Daten ist variabel und für jeden Pakettyp gibt es ein Struct, welches die eigentlichen Daten enthält. Als Code sieht das dann in etwa so aus:typedef struct { unsigned short type; unsigned int data_length; char *data; } protocol_header;
typedef struct { char name[16]; char password[32]; } protocol_login_request;
wie würdet ihr das machen und was kann ich noch verbessern. hab solche Protkolle zwar schon gemacht aber diesmal will ich es gleich richtig machen.
mfg blan
-
dann solltest du auf ein erweiterares format setzen - z.b. ebml
-
r0nny schrieb:
dann solltest du auf ein erweiterares format setzen - z.b. ebml
Ne das Protokoll muss garnicht erweiterbar sein. Hat sonst niemand mehr ein Verbesserungsvorschlag oder ähnliches?
mfg blan
-
Bei Binär-Protokollen musst du auf drei Dinge achten: 1. Endianess 2. Padding bei Strukturen 3. Andere Darstellung von Typen (gilt besonders für Fließkomma-Typen)
-
rüdiger schrieb:
Bei Binär-Protokollen musst du auf drei Dinge achten: 1. Endianess 2. Padding bei Strukturen 3. Andere Darstellung von Typen (gilt besonders für Fließkomma-Typen)
kannst du mal genau sagen, was du damit meinst. was Endian, Padding usw.. ist weiss ich schon - aber wieso muss ich zB auf Endian achten? ich übertag doch meine daten zB Byteweise und setz sie auf bei der Gegenstelle wieder so wie sie kommen zusammen?
Und was meinst du genau mit "Darstellung von Typen" ?
mfg blan
-
Die Endianess ist bei Typen die nur 1 byte groß sind wirklich egal. Aber zB ein unsigned long besteht aus mehreren Bytes zB 4. Das heißt die Darstellung auf einem Bigendian-System ist anders, als auf einem Littleendian-System. Du musst daher die Kodierung der Binär-Typen genau festlegen und entsprechend auf dem System umwandeln.
btw. schau dir vielleicht mal ASN.1 ein.
-
achso. so war das gemeint - jetzt hab ich es verstanden. ASN.1 scheint mir keine sprache zu sein, die ich mal so eben lernen kann
wie finde ich denn heraus welches endian mein OS für solche Datentypen verwendet?
mfg blan
-
Das kann dir egal sein. Wichtig ist nur die Konvertierung. Afaik bietet die Socket-API dafür htonl und ntohl (host-to-network-long, network-to-host-long) für 32-Bit Integer und jeweils noch eine mit s gesuffixte Variante für 16-Bit Integer.
/edit:
Für C++ hilft vielleicht http://boost-consulting.com/vault/index.php?directory=Integer, wobei ich glaube, dass es dazu auch was Neueres gibt.
Außerdem könntest du http://www.boost.org/boost/detail/endian.hpp benutzen.