2

データ型のエンディアンを考慮すると問題が発生します。TCP/IPを使用してイーサネット経由でデータを送信する必要があります。ただし、バイトオーダーは、送信時にはビッグエンディアンである必要があり、受信時にはビッグエンディアンである必要があります。したがって、このクラスを使用して送信する前に、すべての日付を逆にしようとします。

class ReverseBinaryReader : BinaryReader
{
    private byte[] a16 = new byte[2];
    private byte[] ua16 = new byte[2];
    private byte[] a32 = new byte[4];
    private byte[] a64 = new byte[8];
    private byte[] reverse8 = new byte[8];
    public ReverseBinaryReader(System.IO.Stream stream) : base(stream) { }

    public override int ReadInt32()
    {
        a32 = base.ReadBytes(4);
        Array.Reverse(a32);
        return BitConverter.ToInt32(a32, 0);
    }

    public override Int16 ReadInt16()
    {
        a16 = base.ReadBytes(2);
        Array.Reverse(a16);
        return BitConverter.ToInt16(a16, 0);
    }

    [ . . . ] // All other types are converted accordingly.

}

これは、変換された値を次のように割り当てるまでは正常に機能します。

ReverseBinaryReader binReader = new ReverseBinaryReader(new MemoryStream(content));

this.Size = binReader.ReadInt16();  // public short Size

たとえば、バイト:0x00、0x02をビッグエンディアンとして保存する場合、メモリにこれを期待します:0x0200ただし、Sizeの短い値は0x0002になります。何故ですか?

何か案は?ありがとう、ピア

//編集2:

問題を少し解決するために、例を示します。

public class Message {
    public short Size;
    public byte[] Content;

    public Message(byte[] rawData)
    {
        ReverseBinaryReader binReader = new ReverseBinaryReader(new MemoryStream(rawData));

        this.Size = binReader.ReadInt16();  // public short Size
        this.Content = binReader.ReadBytes(2); // These are not converted an work just fine.
    }
}

public class prog {
     public static int main()
     {
          TCPClient aClient = new TCPClient("127.0.0.1",999); // Async socket
          aClient.Send(new Message(new byte[] { 0x00, 0x02 } );
     }
}
4

2 に答える 2

1

編集:

これが実際の答えであるため、これを一番上に移動しました。

私はそれを長い間見つめなければなりませんでしたが、ここにあなたのエラーの原因があります.

  • 初期配列は { 0x00, 0x02 } です LE では 0x0200、BE は 0x0002 です
  • ネットワーク経由で送信し、最初の 2 バイトを読み取ると、まだ { 0x00, 0x02 }
  • それを逆にすると、{0x02、0x00} LE は 0x0002、BE は 0x0200 になります。
  • アーキテクチャはリトル エンディアンであるため、0x0002 の「正しい」結果が得られます。

エラーはテスト配列にあります。BitConverter の IsLittleEndian プロパティをチェックすることで、Architecure がリトル エンディアンであることを確認できます。

=====================================================

次のコードは、直接の質問に答えるよりも明確にするためのものです。そして、BitConverter がすべてのアーキテクチャで予測可能であることを示します。

using System;

namespace BitConverterTest
{
    class Program
    {
        static void Main(string[] args)
        {
            UInt32 u32 = 0x01020304;

            byte[] u32ArrayLittle = {0x04, 0x03, 0x02, 0x01};
            byte[] u32ArrayBig = {0x01, 0x02, 0x03, 0x04};

            if (BitConverter.IsLittleEndian)
            {
                if (BitConverter.ToUInt32(u32ArrayLittle, 0) != u32)
                {
                    throw new Exception("Failed to convert the Little endian bytes");
                }
                Array.Reverse(u32ArrayBig); // convert the bytes to LittleEndian since that is our architecture.
                if (BitConverter.ToUInt32(u32ArrayBig, 0) != u32)
                {
                    throw new Exception("Failed to convert the Big endian bytes");
                }
            } else
            {
                Array.Reverse(u32ArrayLittle); // we are on a big endian platform
                if (BitConverter.ToUInt32(u32ArrayLittle, 0) != u32)
                {
                    throw new Exception("Failed to convert the Little endian bytes");
                }
                if (BitConverter.ToUInt32(u32ArrayBig, 0) != u32)
                {
                    throw new Exception("Failed to convert the Big endian bytes");
                }
            }
        }
    }
}
于 2012-10-04T20:15:23.160 に答える
0

次のことを試してください。

public override Int16 ReadInt16()
{
    a16 = base.ReadBytes(2);
    return ((Int16)a16[1] * 0x00FF) + (Int16)a16[0];
}

public override int ReadInt32()
{
    a32 = base.ReadBytes(4);
    return ((int)a32[3] * 0x00FFFFFF) + (int)a32[2] * 0x0000FFFF) + (int)a32[1] * 0x000000FF) + (int)a32[0];
}

これが機能する理由については、0x00、0x02 が 0x0200 であると予想される場合は、リトルエンディアンを使用しています (最下位バイトが最初になるため)。

BitConverter はシステム依存であり、実装はそうではないため、合理的な場所から離れることをお勧めします。

于 2012-10-04T16:51:47.863 に答える