it-swarm.com.de

C # Little Endian oder Big Endian?

In der Dokumentation der Hardware, die es uns ermöglicht, sie über UDP/IP zu steuern, habe ich folgendes gefunden:

In diesem Kommunikationsprotokoll ist DWORD ein 4-Byte-Datenwort, Word ist ein 2-Byte-Datenformat BYTE ist ein Einzelbyte-Datum. Das Speicherformat ist Little Endian, nämlich 4 Byte (32 Bit) -Daten werden gespeichert als: d7-d0, d15-d8, d23-d16, d31-d24; Doppelbytes (16 Bit) -Daten werden gespeichert als: d7-d0, d15-d8.

Ich frage mich, wie dies in C # übersetzt wird. Muss ich erst konvertieren, bevor ich es übersende? Zum Beispiel, wenn ich eine 32-Bit-Ganzzahl oder eine 4-stellige Zeichenfolge senden möchte?

55
TimothyP

C # selbst definiert nicht die Endianness. Bei jeder Konvertierung in Bytes treffen Sie jedoch eine Auswahl. Die BitConverter -Klasse verfügt über ein IsLittleEndian - Feld, in dem Sie angeben können, wie sich das Verhalten verhält, es hat jedoch keine Wahl. Dasselbe gilt für BinaryReader/BinaryWriter.

Meine MiscUtil library verfügt über eine EndianBitConverter-Klasse, mit der Sie die Endianness definieren können. Es gibt ähnliche Entsprechungen für BinaryReader/Writer. Ich habe keine Online-Gebrauchsanleitung, aber sie sind trivial :)

(EndianBitConverter verfügt auch über eine Funktionalität, die im normalen BitConverter nicht vorhanden ist, dh Konvertierungen in einem Byte-Array vor Ort.)

74
Jon Skeet

Sie können auch verwenden

IPAddress.NetworkToHostOrder(...)

Für kurz, int oder lang.

43
Jan Bannister

Re little-endian, die kurze Antwort (dazu muss ich irgendetwas tun) ist "wahrscheinlich nicht, aber es hängt von Ihrer Hardware ab". Sie können mit überprüfen:

bool le = BitConverter.IsLittleEndian;

Abhängig davon, was dies sagt, möchten Sie möglicherweise Teile Ihrer Puffer umkehren. Alternativ hat Jon Skeet spezifische Endian-Konverter hier (EndianBitConverter suchen).

Beachten Sie, dass Itanien (zum Beispiel) Big-Endian sind. Die meisten Intels sind Little Endian.

Bezüglich der spezifischen UDP/IP ...?

10
Marc Gravell

Sie müssen über die Reihenfolge der Netzwerk-Bytes sowie die CPU-Endian-Ness wissen.

Normalerweise konvertieren Sie Daten für TCP/UDP-Kommunikationen immer in die Bytereihenfolge des Netzwerks mit der Funktion htons (und ntohs und den zugehörigen Funktionen).

Normalerweise ist die Netzwerkreihenfolge Big-Endian, aber in diesem Fall (aus irgendeinem Grund!) Ist die Kommunikation Little Endian, daher sind diese Funktionen nicht sehr nützlich. Dies ist wichtig, da Sie nicht davon ausgehen können, dass die UDP-Kommunikationsverbindungen, die sie implementiert haben, anderen Standards entsprechen. Das macht es auch schwierig, wenn Sie über eine Big-Endian-Architektur verfügen, da Sie einfach nicht alles mit htons verpacken können, wie Sie sollten:

Wenn Sie jedoch aus einer Intel x86-Architektur stammen, sind Sie bereits Little-Endian. Senden Sie also die Daten einfach ohne Konvertierung.

3
gbjbaanb

Ich spiele mit gepackten Daten in UDP Multicast herum und ich brauchte etwas, um UInt16-Oktette neu zu ordnen, da ich einen Fehler im Paket-Header (Wireshark) bemerkt habe.

    private UInt16 swapOctetsUInt16(UInt16 toSwap)
    {
        Int32 tmp = 0;
        tmp = toSwap >> 8;
        tmp = tmp | ((toSwap & 0xff) << 8);
        return (UInt16) tmp;
    }

Im Falle von UInt32

    private UInt32 swapOctetsUInt32(UInt32 toSwap)
    {
        UInt32 tmp = 0;
        tmp = toSwap >> 24;
        tmp = tmp | ((toSwap & 0xff0000) >> 8);
        tmp = tmp | ((toSwap & 0xff00) << 8);
        tmp = tmp | ((toSwap & 0xff) << 24);
        return tmp;
    }

Dies ist nur zum Testen

    private void testSwap() {
        UInt16 tmp1 = 0x0a0b;
        UInt32 tmp2 = 0x0a0b0c0d;
        SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
        SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
        Debug.WriteLine("{0}", shb1.ToString());
        Debug.WriteLine("{0}", shb2.ToString());
        SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
        SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
        Debug.WriteLine("{0}", shb3.ToString());
        Debug.WriteLine("{0}", shb4.ToString());
    }

von welcher Ausgabe war dies:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
0
Marko Samirić

Wenn Sie analysieren und die Leistung nicht kritisch ist, betrachten Sie diesen sehr einfachen Code:

private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
{
    return array.Skip (offset).Take (length).Reverse ().ToArray ();
}

int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);
0
mafu