C#小端或大端?

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

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

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

C#本身并没有定义字节顺序。 但是,每当你转换为字节,你正在做出select。 BitConverter类有一个IsLittleEndian字段来告诉你它将如何performance,但它没有给出select。 BinaryReader / BinaryWriter也是如此。

我的MiscUtil库有一个EndianBitConverter类,允许你定义字节序; BinaryReader / Writer有类似的等价物。 没有在线使用指南我很害怕,但他们是微不足道的:)

(EndianBitConverter也有一个function,这个function在普通的BitConverter中不存在,就是在一个字节数组中就地进行转换。)

你也可以使用

IPAddress.NetworkToHostOrder(...) 

简而言之,int或long。

小端,短的答案(我需要做什么)是“可能不是,但它取决于你的硬件”。 你可以检查:

 bool le = BitConverter.IsLittleEndian; 

根据这个说法,你可能想要将部分缓冲区翻转。 另外,Jon Skeet 在这里有特定的endian转换器(查找EndianBitConverter)。

请注意,itanium(例如)是big-endian。 大多数英特尔都是小端。

重新具体的UDP / IP …?

您需要了解networking字节顺序以及CPU端位置。

通常,对于TCP / UDP通信,您总是使用htons函数(以及ntohs及其相关函数)将数据转换为networking字节顺序。

通常networking顺序是大端,但在这种情况下(出于某种原因!)通信是小端,所以这些function不是很有用。 这一点很重要,因为你不能假设他们已经实现的UDP通信遵循任何其他的标准,如果你有一个大端的体系结构,它也会使生活变得困难,因为你不应该用一种方式来包装所有的东西:-(

但是,如果你来自Intel x86架构,那么你已经是小端,所以只需发送数据而不用转换。

或者您可以使用此代码将BitConverter切换到大端:

 typeof (BitConverter).GetRuntimeField("IsLittleEndian").SetValue(null, false); 

并切换回小端:

 typeof (BitConverter).GetRuntimeField("IsLittleEndian").SetValue(null, true); 

我正在使用UDP Multicast打包的数据,我需要重新sortingUInt16八位组,因为我注意到包头(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; } 

这只是为了testing

  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} 

如果你正在分析和性能不重要,考虑这个非常简单的代码:

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