Endianess ändern

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von seh.

    Endianess ändern

    Hallo,

    ich bin aktuell dabei in die Photon3Unity3D.dll reinzuschauen um zu verstehen wie das Networking dort implementiert wurde.
    Dabei hat mich erstmal interessiert wie das empfangen beim Client von Daten funktioniert.

    Ich verstehe auch soweit den Gedanken hinter der Vorgehensweise der Library, was mich allerdings ständig stört ist, dass die Library, Daten in einer anderen Reihenfolge verschickt als ich das gewohnt bin. Und zwar werden, um die Länge des Payloads auszulesen, Byte Idx. 1 - 4 ausgelesen.

    C#-Quellcode

    1. var array = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x0A };


    Doch dann werden die Bytes erstmal wie folgt geshiftet:

    C#-Quellcode

    1. int num2 = array[1] << 24 | array[2] << 16 | array[3] << 8 | array[4];


    Hier wird doch einfach nur die Endianess geändert oder? Ich habe mal zu Testzwecken folgendes getan:

    C#-Quellcode

    1. int num2 = BitConverter.ToInt32(bData.Skip(1).Reverse().ToArray(), 0);


    Bei beidem kommt dasselbe Ergebnis raus. Ich frage mich allerdings trotzdem ob ich das einfach so auf diese Weise auch machen kann oder ob bei dem Reverse()-n der Bytes auch was schief gehen kann sodass am Ende nicht dieselbe Zahl rauskommt?

    Danke im Voraus
    Grüße

    seh schrieb:

    Ich frage mich allerdings trotzdem ob ich das einfach so auf diese Weise auch machen kann oder ob bei dem Reverse()-n der Bytes auch was schief gehen kann

    Kannst du so machen, das sollte in Ordnung gehen. Musst dir aber bewusst sein, dass das sehr Inperformant ist, also warum nicht so wie oben machen?
    Du solltest bei int nicht annehmen, dass irgend eine Endian-ess vorhanden ist.
    Ein int ist ein int. Der besteht aus vier einzelnen Bytes. .NET ist es dabei egal, ob diese Bytes von der Hardware im BigEndian- oder LittleEndian-Format vorliegen. Wichtig ist nur, dass bei allen Operationen das richtige Ergebnis herauskommt.
    Insofern kann man die Frage "Hier wird doch einfach nur die Endianess geändert oder?" nicht ohne Weiteres bejahen. array[1] ist einfach das höchstwertigste Byte. Dies lässt darauf schließen, dass die Library Daten im BigEndian-Format über Netzwerke transportiert. Wo dieses höchstwertigste Byte dann schlussendlich im RAM landet, wenn man es in den int gestopft hat, ist völlig unerheblich. Der Code, der aus diesen im BigEndian-Format abgelegten Bytes einen int macht ist auf BigEndian- und LittleEndian-Prozessoren exakt der gleiche. 1 << 8 wird immer 256 ergeben. Egal, ob das auf BigEndian- oder LittleEndian-Hardware ausgeführt wird.

    Nebenbei: Ich finde übrigens BigEndian wesentlich angenehmer zu lesen als LittleEndian, weil aufeinanderfolgende Bytes von links nach rechts geschrieben werden. (Vergleiche: {0x00, 0x00, 0x01, 0x00} => 0x00000100 vs {0x00, 0x00, 0x01, 0x00} => 0x00010000) Deshalb verstehe ich nicht, warum Du das als störend empfindest. Möchtest Du Deine Rationale dahinter erklären?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hallo ihr Beiden ( @Niko Ortner und @Bluespide),

    danke für eure Antworten.

    @Niko du hast Recht, jetzt anhand diesem Beispiel ist es viel einfacher abzulesen, mir ist das nur noch nicht aufgefallen weil ich es anscheinend immer gewohnt war mit LittleEndian zu arbeiten.
    Daran wird es auch liegen,dass mich das stört. Die Sache ist aber doch jetzt, dass wenn ich zum Beispiel einen Mitschnitt von so einem Netzwerkpaket binär abspeichere und dann mit z.B. einem BinaryReader die Werte auslesen möchte wie z.B. die o.g. Länge des Pakets welche als 4-Byte Integer vorliegt, dann kann ich den BinaryReader ja nicht nutzen. Der BinaryReader spuckt mir dann einfach das falsche Ergebnis aus, d.h. ich muss jetzt einen eigene Klasse schreiben, welche von dem BinaryReader erbt, und die Methoden überschreibt damit ich am Ende noch shiften kann. (Bzw. es gibt noch andere Möglichkeiten, wie z.B. Extensions, aber ich kenne und hab auch keinen Weg gefunden, den BinaryReader beizubringen er soll in BE lesen.)

    Verstehst du?

    Oder kann man dem BinaryReader irgendwie beibringen BigEndian zu lesen?
    Ja, das ist leider ein bekanntes Problem. Der BinaryReader arbeitet in dem Format, in dem die Hardware arbeitet. Man kann, wie Du schon erwähnt hast, eine Klasse davon ableiten, BinaryReader.IsLittleEndian abrfragen und bei Bedarf bei den entsprechenden Methoden die Bytes umdrehen. Andere Möglichkeit mit dem BinaryReader gibt es wohl keine.
    Alternativ kannst Du bestehende Bibliotheken verwenden: github.com/jamesqo/Be.IO
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils