Designfrage: Datentypübertragung über das Netzwerk
-
Hallo!
Ich bekomme Daten über ein definiertes internes Protokoll. Auf das Protokoll habe ich keinen Einfluss, d.h. ich kann nicht die Art der Datenübertragung ändern. Im Prinzip werden mir viele Tupel gesendet, wobei alle Tupel dieselben Eigenschaften haben. Nur der Datentyp ist unterschiedlich:
class Tupel { public: // [...] Lauter Gemeinsamkeiten, alles identisch vom Aufbau ??? m_value; // Der eigentliche Wert };Ich bekomme den Wert binär codiert über das Protokoll mitgeteilt:
Nächster Datentyp: int16
Anzahl Bytes: 2oder
Nächster Datentyp: int64 (ist auch das Maximum)
Anzahl Bytes: 8oder
*Nächster Datentyp: BCD2
Anzahl Bytes: 1
*
oder z.B.Nächster Datentyp: Real
Anzahl Bytes: (Gerade nicht im Kopf)Später soll ggfs. mit diesen Daten weiter gerechnet werden. Jetzt bin ich am überlegen, wie ich diese in einer Klasse Tupel am besten speichere.
Mein erster Ansatz
class Tupel als Template-Klasse. Wäre am "saubersten" ist aber Mist, weil ich hinterher an der Netzwerschnittstelle z.B. nicht mehr folgendes machen könnte:std::vector<Tupel> vecTupel; NetworkInterface.receive(&vecTupel); for(std::size_t i=0; i<vecTupel.size(); ++i) { cout<<vecTupel[i]<<endl; }Mein Zweiter Ansatz
Ich baue Tupel wie folgt auf:class Tupel { public: // [...] Lauter Gemeinsamkeiten, alles identisch vom Aufbau Type getType() { [...] }; bool isRawValue() { [...] } long double m_value; // Der eigentliche Wert std::int64 m_rawValue; // Die wirklich empfangenen Bytes };Bekomme ich jetzt int16 bis int64 oder real, dann packe ich die in den "long double m_value". Bekomme ich BCD oder anderen exotischen Kram, landet der in "m_rawValue". Über "isRawValue" kann der Benutzer dann später prüfen, wo der Wert drinne ist und bei Bedarf mit getType() dann selber entscheiden, was er macht. Nachteile: Man rechnet auch bei ints ständig mit double-Werten

Was haltet ihr von meinen Ideen? Wie würdet ihr das lösen?
-
Wieso überhaupt speichern, du wirst diese Tupel im nächsten Schritt ja sicher noch irgendwie interpretieren wollen!? Man könnte also einfach sowas machen:
class Interpreter { // ... void consume(int16_t v) { // ... } void consume(int64_t v) { // ... } void consume(double v) { // ... } void consume(int v) { // ... } }; class ValueStream { ... void feed(Interpreter& interpreter) { // Werte lesen und die entsprechenden Methoden des Interpreters aufrufen } };
-
Du hast schon recht, die werden später interpretiert. Aber an einer ganz anderen Stelle und je nach Interpreter auch nicht alle! Deswegen möchte ich gerne eine logische Trennung zwischen diesem Netzwerk/Protokoll und der Verarbeitung haben.
Beispiel:
std::vector<Tupel> vecTupel; NetworkInterface.receive(&vecTupel); Interpreter.feed(vecTupel);Je nach Art des Interpreters passiert jetzt folgendes:
void Interpreter::feed(std::vector<Tupel>& vecTupel) { for(std::size_t i=0; i<vecTupel.size(); ++i) { if(vecTupel[i].getDescription() != Tupel::WeatherData) { continue; } if(vecTupel[i].getDescription() == Tupel::Temperature) { sumTemperatures += vecTupel[i].m_value; // Bloedes Beispiel } if(vecTupel[i].getDescription() == Tupel::AirHuminity) { currentAirHuminity = vecTupel[i].m_value; } // [...] } }Ich bekomme also nicht nur Anzahl Bytes und den Datentyp (int16, ...) sondern auch eine Beschreibung was der Tupel darstellt (getDescription()). Das hätte ich erwähnen müssen, sorry.
-
Ist es paketbasiert oder streambasiert, d.h. gibt es eine eindeutige Paketzuordnung/Trennung? Wenn ja, wie warden die einzelnen Pakete unterschieden? So wie es ausschaut, ist es paketbasiert.
Bei Paketen werden die Daten einfach vollstaendig fuer ein Paket gesammelt (parsen) und der ganze Byteblob einem Konstruktionsmechanismus uebergeben (interpretieren), der das zugehoerige programminterne Objekt erstellt. Dabei muss ein uint8_t nicht zwingend als uint8_t intern dargestellt werden. Wie die Daten intern dargestellt werden haengt vom Einsatzfeld und Anwendung ab.
-
ArmAberSexy schrieb:
Du hast schon recht, die werden später interpretiert. Aber an einer ganz anderen Stelle und je nach Interpreter auch nicht alle! Deswegen möchte ich gerne eine logische Trennung zwischen diesem Netzwerk/Protokoll und der Verarbeitung haben.
Knivils Frage passt da schon ganz gut. Wie lange willst du das mit dem Speichern von empfangenen Daten durchziehen? Bis dir alles wegen mangelndem Speicher um die Ohren fliegt? Klar kannst du empfangene Daten puffern, aber die Größe des verwendeten Buffers sollte dabei von dir bestimmt werden und nicht davon mit wieviel Daten dein Kommunikationspartner dich gerade zufällig so vollballert.
-
ArmAberSexy schrieb:
Du hast schon recht, die werden später interpretiert. Aber an einer ganz anderen Stelle und je nach Interpreter auch nicht alle! Deswegen möchte ich gerne eine logische Trennung zwischen diesem Netzwerk/Protokoll und der Verarbeitung haben.
Perfekt, genau das hast du mit meinem obigen Vorschlag...

-
Ich versuche mich mal daran zu orientieren
