Protokoll-Umsetzung in C++ - eure Meinung
-
Kann es sein, dass du Bit und Byte verwechselst? bool ist nicht ein bit, sondern byte
-
Nein, bool hat zwei Zustände: 0/1 oder true/false. Also ein Bit.
http://www.cppreference.com/wiki/keywords/bool
Byte sind 8 Bit. Für ein Byte gibt es aber in C++ kein Datentyp. Ein char ist aber i.d.R. ein Byte. Oder im TR1 gibt es:
#include <tr1/cstdint> std::tr1::int8_t byte; // 8 Bit mit Vorzeichen std::tr1::uint8_t byte; // 8 Bit ohne VorzeichenOder bei MS Visual C++:
__int8 byte; // 8 Bit mit Vorzeichen unsigned __int8 byte; // 8 Bit ohne Vorzeichen
-
boolkann zwar nur 2 Zustände haben, belegt aber in der Regel mindestens ein Byte (bzw. einechar-Größe) Speicher (d.h.sizeof(bool) >= 1). Zum einen, weil der Standard nicht unbedingt die Existenz von Bits vorraussetzt, zum anderen weil ein Byte / eincharnunmal die kleinste addressierbare Einheit ist und sich auf Bitebene so blöd rechnet (stell dir vor, du hättest einenbool, der ein Bit belegt und im Anschluss einenchar, die die restlichen 7 Bits und das erste Bit des nächsten Byts belegt. Das wird eine fröhliche Rechnerei, wenn man auf dencharzugreifen will).
-
Ach so ja, Ok auf Bitebene.
Ich war jetzt ganz auf den Wertebereich der C++-Datentypen fixiert.
Wie die Datenpakete des Protokolls nacher aufgebaut werden habe ich jetzt hier erstmal ganz außen vor gelassen. Da kommt ja auch noch das Thema Endianess dazu, wo ich auch nicht weiß, wie ich das mache... Das ganze wird in den Funktionen gekapselt (Execute()).
-
Ich stecke gerade im Thema "Erstellung der Datenpakete" fest:
Eigentlich hatte ich daran gedacht die hton/ntoh Funktionen für die richtige Endianess zu nutzen. Das Protokoll schreibt nämlich Network-Byteorder für seine Wörter und Doppelwörter vor.
Nun bin ich bei der Suche auf folgende Aussage von Tachyon getoßen:
Tachyon schrieb:
htons(host to net short) undhtonl(host to net long) sind erstmal nur dafür da, IP-Header Standardkonform zu befüllen und helfen einem nur bei 16 Bit bzw. 32 Bit unsigned Integer Werten. Für Endian-Konvertierung sind diese nur sehr bedingt geeignet und auch nicht gedacht.
Weitgehende plattfromunabhängigkeit ist es am Besten, seine Werte als ASCII-String zu übertragen/speichern.Wie die Datenpakete aufgebaut sind steht nun aber fest. Somit muss ich die Endianess der Plattform beachten und ggf. konvertieren. Wie mache ich das nun am besten?

-
Roger Wilco schrieb:
Byte sind 8 Bit. Für ein Byte gibt es aber in C++ kein Datentyp.
sizeof( char ) ist per Definition 1, d.h. char deckt immer und überall genau ein Byte ab.
Wenn du die Daten im ASCII Format überträgst stellt Endianess kein Problem für dich da, da die Konvertierung vom Host unter Berücksichtigung seiner Endianess durchführt wird.
Wenn du die Daten allerdings binär überträgst musst du im Protokoll spezifizieren, welches Datenformat (z.B. Endianess) benutzt wird. Der Host muss seine eigene Endianess kennen und, falls nötig, eine Konvertierung durchführen.boost definiert für bekannte CPU Typen die Konstanten
BOOST_LITTLE_ENDIAN/BOOST_GIB_ENDIAN und BOOST_BYTE_ORDER. Wenn du boost nicht benutzen kannst oder willst oder eine exotische CPU hast kannst du die Defines selbst setzen.
Eine andere Möglichkeit wäre vielleicht folgendes:char IntRep[sizeof( int )] = { 0 }; IntRep[0] = 1; if( *(int*)( IntRep ) == 1 ) { // little endian } else { // big endian }Aber damit wäre ich lieber vorsichtig, ist mehr ein Hack als anerkannte Endianess Bestimmung

-
DocShoe schrieb:
sizeof( char ) ist per Definition 1, d.h. char deckt immer und überall genau ein Byte ab.
Falscher Schluss.
sizeofgibt nicht die Größe in Bytes zurück, sondern inchars. Demnach istsizeof(char)immer per Definition 1, trotzdem kanncharauch mehrere Byte groß sein.
-
Mein größter Kritikpunkt an der Umsetzung: Protocol wird mit nur einem L geschrieben.
Den Rest habe ich mir nicht angesehen.

-
Fellhuhn schrieb:
Protocol wird mit nur einem L geschrieben.
-
Bei mir ist es so, dass ich ein gegebenes Protokoll habe. Das möchte ich umsetzen. Es wird immer ein Datenpaket als Anfrage abgeschickt und es kommt immer genau ein Datenpaket (mit gleichem Header) als Antwort.
Die Datenpakete setzten sich aus Bytes (z.B. Funktons-ID), Wörtern (16Bit - Register-Adressen oder Daten) und Doppelwörtern (32Bit - Daten) zusammen. Per Definition ist die Byteorder "Big-Endian". Eigentlich soll das ganze auf Windows-PCs laufen, aber ich möchte lernen portabel zu schreiben. Mein Kollege schreibt mit VC6.0 immer mit MFC und im C-Klassen-Stil. Ich selber benutze VS2008. Daher wollte ich hier nach Feedback fragen, um es "richtig(er)" zu machen...
Die Funktions-Klassen besitzen die Methode Execute(). Hier soll das Datenpaket geschnürrt werden. Ich dachte da an sowas:
#include "WinSock2.h" //hton/ntoh - nur Windows #include <sstream> //stringstream void Funktion::Execute(){ std::stringstream data(std::stringstream::out | std::stringstream::in | std::stringstream::binary); data << m_funcId // unsigned __int8 << htons(m_address) // unsigned __int16 << htonl(m_data); // unsigned __int32 m_socket.SendRequst(data.str()); // Auf Antwort warten... // Antwort lesen und auswerten // evtl. Daten ins Datenobjekt schreiben oder Exception werfen... }
-
Fellhuhn schrieb:
Mein größter Kritikpunkt an der Umsetzung: Protocol wird mit nur einem L geschrieben.
Ups, habe ich geändert...Fellhuhn schrieb:
Den Rest habe ich mir nicht angesehen.

Schade...

