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 但是大小的短值将变为 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
  • 您通过网络发送它,并读取前两个字节仍然 { 0x00, 0x02 }
  • 你把它反转给你 {0x02, 0x00} LE 是 0x0002,BE 是 0x0200
  • 您的架构是 Little Endian,因此您会得到 0x0002 的“正确”结果。

因此错误在您的测试数组中。您可以通过检查 BitConverter 上的 IsLittleEndian 属性来验证您的架构是否为小端。

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

以下代码旨在帮助澄清,而不是回答您的直接问题。并表明 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 那么您使用的是 little-endian (因为最低有效字节在前)。

由于 BitConverter 是系统依赖的,而您的实现不是,我建议在合理的情况下尽量远离它。

于 2012-10-04T16:51:47.863 回答