Byte-Reihenfolge mit einer großen Anzahl von Zeichen in C

8

Hey Leute, Frage von einem C / Networking-Neuling ...

Ich mache eine Socket-Programmierung in C und versuche, mit Byte-Ordnungsproblemen zu ringen. Meine Anfrage (Senden) ist in Ordnung, aber wenn ich Daten erhalte, sind meine Bytes nicht in Ordnung. Ich beginne mit so etwas ...

%Vor%

Wenn man sich mit dieser Antwort beschäftigt, scheint jedes 16-Bit-Wort seine Bytes umzukehren (ich benutze UDP). Ich habe versucht, das zu beheben, indem ich so etwas mache ...

%Vor%

Das funktioniert gut, wenn ich die Daten als Kurzform behandle, aber wenn ich den Zeiger wieder auf ein Zeichen setze, werden die Bytes umgekehrt. Was mache ich falsch?

Danke!

    
ChrisDiRulli 08.02.2009, 17:04
quelle

6 Antworten

10

Ok, es scheint Probleme auf zwei verschiedenen Ebenen zu geben. Ein Teil der Verwirrung scheint hier auf die Verwendung von Zeigern zurückzuführen zu sein, auf welche Art von Objekten sie zeigen, und dann auf die Interpretation der Kodierung der Werte im Speicher, auf die der Zeiger zeigt.

Die Codierung von Multi-Byte-Entitäten im Speicher wird als Endianess bezeichnet. Die beiden üblichen Kodierungen werden als Little Endian (LE) und Big Endian (BE) bezeichnet. Bei LE wird eine 16-Bit-Menge wie ein Kurzschluss zuerst als niedrigstwertiges Byte (LSB) codiert. Unter BE wird das höchstwertige Byte (MSB) zuerst codiert.

Per Konvention kodieren Netzwerkprotokolle normalerweise Dinge in etwas, das wir "Netzwerk-Byte-Reihenfolge" (NBO) nennen, das auch dasselbe ist wie BE. Wenn Sie Speicherpuffer auf Big-Endian-Plattformen senden und empfangen, treten keine Konvertierungsprobleme auf. Ihr Code wäre dann jedoch plattformabhängig von der BE-Konvention. Wenn Sie portablen Code schreiben möchten, der sowohl auf LE- als auch BE-Plattformen korrekt funktioniert, sollten Sie nicht von der Endgültigkeit der Plattform ausgehen.

Endian-Portabilität ist das Ziel von Routinen wie ntohs () , ntohl () und > htons () und htonl () . Diese Funktionen / Makros sind auf einer bestimmten Plattform definiert, um die erforderlichen Konvertierungen am sendenden und empfangenden Ende durchzuführen:

  • htons () - Konvertiert einen kurzen Wert von der Host-Reihenfolge in die Netzwerk-Reihenfolge (zum Senden)
  • htonl () - Konvertiert einen langen Wert von der Host-Reihenfolge in die Netzwerkreihenfolge (zum Senden)
  • ntohs () - Konvertiert den Kurzwert von der Netzwerkreihenfolge in die Host-Reihenfolge (nach dem Empfang)
  • ntohl () - Konvertiert den langen Wert aus der Netzwerkreihenfolge in die Host-Reihenfolge (nach dem Empfang)

Verstehen Sie, dass Ihr Kommentar über den Zugriff auf den Speicher bei der Rückgabe an Zeichen keinen Einfluss auf die tatsächliche Reihenfolge der Entitäten im Speicher hat. Das heißt, wenn Sie auf den Puffer als eine Reihe von Bytes zugreifen, sehen Sie die Bytes in der Reihenfolge, in der sie tatsächlich in den Speicher geschrieben wurden, unabhängig davon, ob Sie eine BE- oder LE-Maschine haben. Wenn Sie also nach dem Empfang einen NBO-codierten Puffer betrachten, wird das MSB zuerst - immer. Wenn Sie nach der Konvertierung in die Host-Reihenfolge den Ausgabepuffer betrachten, bleibt die Byte-Reihenfolge unverändert, wenn Sie eine BE-Maschine haben. Umgekehrt werden die Bytes auf einer LE-Maschine nun alle im konvertierten Puffer umgekehrt.

Schließlich bezieht sich die Variable total in Ihrer Konvertierungsschleife auf Bytes. Sie greifen jedoch auf den Puffer als shorts zu. Ihr Schleifenwächter sollte nicht total sein, sollte aber:

sein

total / sizeof( unsigned short )

, um die Doppelbyte-Natur jedes short zu berücksichtigen.

    
Tall Jeff 08.02.2009, 19:11
quelle
3
  

Das funktioniert, wenn ich die Daten als Kurzform behandle, aber wenn ich den Zeiger erneut auf ein Zeichen setze, werden die Bytes umgekehrt.

Das ist, was ich erwarten würde.

  

Was mache ich falsch?

Sie müssen wissen, was der Absender gesendet hat: wissen, ob es sich bei den Daten um Bytes handelt (die nicht reversiert werden müssen), oder um kurze oder lange (die das tun).

Google für Tutorials, die den APIs ntohs , htons und htons zugeordnet sind.

    
ChrisW 08.02.2009 17:15
quelle
2

Es ist nicht klar, was aResponse darstellt (Zeichenkette? struct?). Endianness ist nur für numerische Werte relevant, nicht char s. Sie müssen auch sicherstellen, dass auf der Senderseite alle numerischen Werte von Host in Netzwerk-Byte-Reihenfolge ( hton* ) konvertiert werden.

    
Zach Scrivena 08.02.2009 17:15
quelle
1

Abgesehen von Ihrer ursprünglichen Frage (die meiner Meinung nach bereits beantwortet wurde) sollten Sie sich Ihre malloc -Anweisung ansehen. malloc weist Bytes zu und eine vorzeichenlose Abkürzung ist höchstwahrscheinlich zwei Byte.

Ihre Aussage sollte wie folgt aussehen:

%Vor%     
olli-MSFT 08.02.2009 17:18
quelle
0

Die Netzwerk-Byte-Reihenfolge ist Big Endian, also müssen Sie es in Little Endian konvertieren, wenn Sie wollen, dass es sinnvoll ist, aber wenn es nur ein Array ist, sollte es keinen Aufwand machen, wie sendet der Absender seine Daten ?

    
CiNN 08.02.2009 17:09
quelle
0

Bei einem einzelnen Byte interessiert uns vielleicht die Byte-Reihenfolge nicht.

    
Vijay 30.06.2011 11:59
quelle

Tags und Links