硬件-C#小端还是大端?

在允许我们通过UDP / IP对其进行控制的硬件文档中,我发现以下片段:

在此通信协议中,DWORD是4字节数据,WORD是2字节数据,   BYTE是单字节数据。 存储格式为小字节序,即4字节(32bits)的数据存储为:d7-d0,d15-d8,d23-d16,d31-d24; 双字节(16位)数据存储为:d7-d0,d15-d8。

我想知道这如何转换为C#?发送之前,我是否必须转换内容?例如,如果要发送32位整数或4个字符串?

TimothyP asked 2019-10-08T12:12:21Z
6个解决方案
76 votes

C#本身未定义字节序。 但是,无论何时转换为字节,您都在做出选择。 BitConverter类具有IsLittleEndian字段来告诉您它将如何运行,但没有给出选择。 BinaryReader / BinaryWriter也是如此。

我的MiscUtil库有一个EndianBitConverter类,它允许您定义字节序; BinaryReader / Writer有类似的等效项。 恐怕没有在线使用指南,但它们并不重要:)

(EndianBitConverter还具有普通BitConverter中不存在的功能,该功能可以在字节数组中进行就地转换。)

Jon Skeet answered 2019-10-08T12:12:52Z
43 votes

你也可以使用

IPAddress.NetworkToHostOrder(...)

简短,完整或较长。

Jan Bannister answered 2019-10-08T12:13:18Z
10 votes

关于小尾数,简短的答案(我需要做任何事情)是“可能没有,但这取决于您的硬件”。 您可以通过以下方式进行检查:

bool le = BitConverter.IsLittleEndian;

根据这句话,您可能想要反转缓冲区的某些部分。 另外,Jon Skeet在此具有特定尾数转换器(查找EndianBitConverter)。

请注意,例如,钛是大端的。 大多数英特尔都是低端的。

是特定的UDP / IP ...吗?

Marc Gravell answered 2019-10-08T12:14:10Z
3 votes

您需要了解网络字节顺序以及CPU字节序。

通常,对于TCP / UDP通讯,总是使用htons函数(和htons及其相关函数)将数据转换为网络字节顺序。

通常,网络顺序为高位优先,但在这种情况下(出于某种原因!),通信是低位优先,因此这些功能不是很有用。 这很重要,因为您不能假设它们实现的UDP通讯遵循任何其他标准,如果您使用的是大端架构,这也会给您带来生活上的困难,因为您不能像应该那样用htons包装所有内容:-(

但是,如果您使用的是Intel x86架构,那么您已经是低位字节序了,因此只需发送数据而无需进行转换。

gbjbaanb answered 2019-10-08T12:14:57Z
0 votes

如果您在解析并且性能并不重要,请考虑以下非常简单的代码:

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);
mafu answered 2019-10-08T12:15:20Z
0 votes

我正在使用UDP组播中的打包数据,并且我需要重新排序UInt16八位字节的内容,因为我注意到数据包头(Wireshark)中存在错误,所以我这样做了:

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

如果是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;
    }

这只是为了测试

    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());
    }

从哪个输出是:

    0B0A: {0}
    0A0B: {0}
    0D0C0B0A: {0}
    0A0B0C0D: {0}
Marko Samirić answered 2019-10-08T12:16:06Z
translate from https://stackoverflow.com:/questions/217980/c-sharp-little-endian-or-big-endian