Netzwerk-Programmierung – Java und .NET benutzen unterschiedliche Repräsentationen für Integer [gelöst]



  • Ich habe eine Netzwerk-Anwendung, die den Server mit Java und den Client durch .NET mit C# realisiert
    (Bitte nicht nachfragen, geht in diesem Fall nicht anders, ich möchte meinen Computer mit meinem Smartphone vernetzen)

    Ich habe das Ganze durch einen BinaryWriter auf der .NET- und einen DataInputStream auf der Java-Seite realisiert. Das Problem ist vermutlich, dass Java und .NET anscheinend die Bytes verschieden anordnen (Little-Endian, Big-Endian), da zum Beispiel...

    BinaryWriter writer = ...
    writer.Write(1); // Es wird der Integer-Wert 1 geschrieben
    
    DataInputStream dis = ...
    dis.readInt() //= 16777216
    

    Das Schreiben von 2 führt zu 33554432
    3 führt zu 50331648
    und so weiter

    Kann mit jemand bestätigen, dass das Problem durch Little-Endian/Big-Endian ensteht (1)
    und weiß jemand, wie man hier Abhilfe schaffen kann (2) oder ob ich mit reinen Byte-Arrays arbeiten muss oder sollte 😞 (3) ?
    Im Bezug auf .NET habe ich bereits gelesen, dass das Verhalten von .NET in dieser Hinsicht nicht geändert werden kann, also das Ändern der Byte-Reihenfolge schlicht nicht unterstützt wird.



  • Ja es ist ein Problem mit der Endianess, hab die Werte mal in den Windows-Taschenrechner eingegeben.

    Schau mal, hier auf StackOverflow hatte jemand das selbe Problem, für C# gibts ne Ersatzklasse die Endianess beachtet.

    Alternativ die einfachste (wenn auch unschöne Methode wäre die Klasse abzuleuten/Wrappen und für jeden gelesenen Integer 4 Bytes einzulesen. Sowas wie:

    uint value1 = ReadByte();
    uint value2 = ReadByte();
    uint value3 = ReadByte();
    uint value4 = ReadByte();
    uint result1 = value1 << 0 + value2 << 8 + value3 << 16 + value4 << 24;
    uint result2 = value4 << 0 + value3 << 8 + value2 << 16 + value1 << 24;
    //für unsigned !!
    


  • ch++ schrieb:

    Kann mit jemand bestätigen, dass das Problem durch Little-Endian/Big-Endian ensteht (1)

    Ja, kann ich bestätigen.

    Im Bezug auf .NET habe ich bereits gelesen, dass das Verhalten von .NET in dieser Hinsicht nicht geändert werden kann, also das Ändern der Byte-Reihenfolge schlicht nicht unterstützt wird.

    Korrekt.
    Und das des DataInputStream laut Java Doku auch nicht.

    und weiß jemand, wie man hier Abhilfe schaffen kann (2) oder ob ich mit reinen Byte-Arrays arbeiten muss oder sollte 😞 (3) ?

    Du kannst auf einer der der beiden Seiten eine fertige Klasse ausserhalb der Standard-Library verwenden.
    z.B. sowas:
    http://www.peterfranza.com/2008/09/26/little-endian-input-stream/

    Oder dir selbst etwas in der Art schreiben.
    Oder ein Text-basiertes Protokoll verwenden. Marke Eigenbau, JSON, XML, ...

    Oder gleich ein SOAP Webservice basteln.
    Das kannst du z.B. relativ einfach mit WCF definieren (Code-first), und dann mit wsdl2java konsumieren.
    Vorausgesetzt du hast schon fertigen selbst gebastelten Netzwerkcode, dann wird die Einstiegshürde bei einem SOAP Service minimal höher sein. Dafür sparst du immer mehr Zeit, je mehr Strukturen/Operationen du übertragen/anbieten willst.

    @DarkShadow44
    Da würde ich eher nen ganzen int lesen und dann maskieren+shiften+verodern. 4 Funktionsaufrufe machen wo einer reicht finde ich nicht gut.



  • Danke für die schnellen Antworten, jetzt weiß ich wenigstens, warum das so schieflief. (Der Fehler hat mir die gesamte Anwendung zum Absturz gebracht)
    Mal sehen, was ich dagegen mache, JSON oder XML-basiertes Protokoll selberbauen wäre zwar für mich kein Problem, aber für diesen Anwendungszweck (Es werden nur der Integer und ein paar Komma-Zahlen gesendet) empfinde ich dies als absolut überdimensioniert.



  • In C# kannst du auch einfach die beiden Methoden IPAddress.HostToNetworkOrder und IPAddress.NetworkToHostOrder benutzen.



  • Der Tipp ist auch gut. Danke!


Anmelden zum Antworten