Frage

ich sende und binäre Daten zu / von einem Gerät in Paketen (64 Byte) zu empfangen. Die Daten haben ein spezielles Format, von denen Teile mit unterschiedlicher Anforderung / Antwort variieren.

Jetzt habe ich einen Dolmetscher für die empfangenen Daten bin der Gestaltung. Einfach durch Positionen Lesen der Daten ist in Ordnung, aber nicht so cool aussehen, wenn ich ein Dutzend verschiedene Antwortformate haben. Ich denke derzeit über ein paar structs zu diesem Zweck erstellen, aber ich weiß nicht, wie wird es mit Polsterung gehen.

Vielleicht gibt es einen besseren Weg?


Siehe auch:

War es hilfreich?

Lösung

Ich habe dies unzählige Male vorher getan: es ist ein sehr häufiges Szenario. Es gibt eine Reihe von Dingen, die ich so gut wie immer.

Sie nicht zu viel Sorgen darüber machen es die effizienteste Sache zur Verfügung.

Wenn wir viel Zeit verbringen und Auspacken Pakete aufzuwickeln tun, dann können wir es immer effizienter sein ändern. Während ich keinen Fall, in dem ich je hatte als noch erlebt habe, habe ich nicht Netzwerk-Router gewesen Umsetzung!

Während structs / Gewerkschaften verwendet, ist der effizienteste Ansatz in der Bezeichnung der Laufzeit, ist es mit einer Reihe von Komplikationen kommt: überzeugende Compiler die structs / Gewerkschaften packen das Oktett Struktur der Pakete müssen Sie übereinstimmen, Arbeit Ausrichtung zu vermeiden und endianness Probleme und ein Mangel an Sicherheit, da gibt es keine oder nur eine geringe Möglichkeit, Plausibilitätsprüfungen zu tun, auf Debug-Builds.

ich oft mit einer Architektur, einschließlich der folgenden Arten von Dingen aufzuwickeln:

  • Ein Paket Basisklasse. Etwaige gemeinsame Datenfelder zugänglich sind (aber nicht änderbar). Wenn die Daten in einem gepackten Format gespeichert ist, dann gibt es eine virtuelle Funktion, die ein gepacktes Paket produzieren.
  • Eine Anzahl von Darstellungsklassen für bestimmte Pakettypen, von den gemeinsamen Pakettyp abgeleitet. Wenn wir eine Verpackungsfunktion verwenden, dann wird jede Präsentation Klasse muss es umsetzen.
  • Alles, was von der spezifischen Art der Präsentation der Klasse abgeleitet werden kann (das heißt eine Pakettyp-Identifikation von einem gemeinsamen Datenfeld), mit als Teil der Initialisierung behandelt wird und ansonsten als nicht änderbar.
  • Jede Präsentation Klasse kann aus einem entpackten Paket konstruiert sein oder werden ordnungsgemäß fehlschlagen, wenn die Paketdaten der ungültigen für diesen Typ ist. Dies kann dann in einer Fabrik für Komfort eingewickelt werden.
  • Wenn wir nicht zur Verfügung haben RTTI, können wir „Arme-Leute-RTTI“ mit dem Paket-ID erhalten, auf die spezifische Präsentation Klasse bestimmen ein Objekt wirklich ist.

Bei alldem ist es möglich (wenn auch nur für Debug-Builds), um sicherzustellen, dass jedes Feld, das veränderbar ist, auf einen vernünftigen Wert gesetzt wird. Während es wie eine Menge Arbeit erscheinen mag, macht es sehr schwierig, ein invalidly formatierte Paket zu haben, ein abgepackte Paket Inhalt mit dem Auge kann mit Hilfe eines Debuggers easilly geprüft (da sie alle in normalen Plattform-native Format Variablen sind).

Wenn wir haben ein effizienteres Speicherschema zu implementieren, das auch in dieser Abstraktion mit wenig zusätzlichen Leistung Kosten eingewickelt werden.

Andere Tipps

Sie müssen structs verwenden und oder Gewerkschaften. Sie müssen Ihre Daten, um sicherzustellen, richtig auf beiden Seiten der Verbindung gepackt sind, und Sie können an jedem Ende zu und von Netzwerk-Byte-Reihenfolge übersetzen wollen, ob es eine Chance, dass auf beiden Seiten der Verbindung mit einem anderen ausgeführt werden könnten, Endianess.

Als Beispiel:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */
typedef struct {
    unsigned int    packetID;  // identifies packet in one direction
    unsigned int    data_length;
    char            receipt_flag;  // indicates to ack packet or keep sending packet till acked
    char            data[]; // this is typically ascii string data w/ \n terminated fields but could also be binary
} tPacketBuffer ;
#pragma pack(pop)   /* restore original alignment from stack */

und dann bei der Zuordnung:

packetBuffer.packetID = htonl(123456);

und dann beim Empfang:

packetBuffer.packetID = ntohl(packetBuffer.packetID);

Hier sind einige Diskussionen über Endianness und Ausrichtung und Struktur Verpackung

Wenn Sie die Struktur nicht packen Sie es an Wortgrenzen und die interne Aufteilung der Struktur ausgerichtet am Ende dann und es ist Größe falsch sein wird.

Es ist schwer zu sagen, was die beste Lösung ist das genaue Format (s) der Daten, ohne zu wissen. Haben Sie darüber nachgedacht Gewerkschaften mit?

Ich bin mit Wuggy. Sie können auch Codegenerierung, dies zu tun. Verwenden Sie einen einfachen Datendefinitionsdatei, die alle Arten Ihr Paket zu definieren, dann ein Python-Skript laufen über es Prototyp Strukturen zu erzeugen und serialiation / Deserialisierung Funktionen für jeden einzelnen.

Dies ist eine "out-of-the-box" Lösung, aber ich würde vorschlagen, einen Blick auf der Python nehmen

scroll top