在允许我们通过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个字符的字符串?
C#本身并没有做出选择 . BitConverter类有一个IsLittleEndian字段来告诉你它将如何表现,但它没有给出选择 . BinaryReader / BinaryWriter也是如此 .
我的MiscUtil库有一个EndianBitConverter类,允许你定义字节序; BinaryReader / Writer有类似的等价物 . 没有在线使用指南我'm afraid, but they'琐碎的:)
(EndianBitConverter还有一个功能,它在普通的BitConverter中不存在,它在字节数组中就地进行转换 . )
你也可以使用
IPAddress.NetworkToHostOrder(...)
简而言之,int或long .
Re little-endian,简短的回答(我需要做什么)是“可能不是,但这取决于你的硬件” . 您可以查看:
bool le = BitConverter.IsLittleEndian;
根据这说明,您可能想要反转部分缓冲区 . 或者,Jon Skeet具有特定端转换器here(寻找EndianBitConverter) .
请注意,itaniums(例如)是big-endian . 大多数英特尔都是小端的 .
重新具体的UDP / IP ......?
您需要了解网络字节顺序以及CPU字节顺序 .
通常,对于TCP / UDP通信,您始终使用htons函数(和 ntohs 及其相关函数)将数据转换为网络字节顺序 .
ntohs
通常网络顺序是big-endian,但在这种情况下(由于某种原因!),comms是小端,所以这些功能不是很有用 . 这很重要,因为你不能假设他们已经实现的UDP通信遵循任何其他标准,如果你有一个大端架构,它也会让生活变得困难,因为你不能用 htons 包装所有内容,因为你应该:-(
htons
但是,如果您来自intel x86架构,那么您已经是little-endian,所以只需发送数据而不进行转换 .
如果您正在解析并且性能不重要,请考虑以下非常简单的代码:
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);
我正在玩UDP Multicast中的打包数据,因为我注意到包头(Wireshark)中有错误,所以我需要重新排序UInt16八位字节,所以我做了这个:
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}
6 回答
C#本身并没有做出选择 . BitConverter类有一个IsLittleEndian字段来告诉你它将如何表现,但它没有给出选择 . BinaryReader / BinaryWriter也是如此 .
我的MiscUtil库有一个EndianBitConverter类,允许你定义字节序; BinaryReader / Writer有类似的等价物 . 没有在线使用指南我'm afraid, but they'琐碎的:)
(EndianBitConverter还有一个功能,它在普通的BitConverter中不存在,它在字节数组中就地进行转换 . )
你也可以使用
简而言之,int或long .
Re little-endian,简短的回答(我需要做什么)是“可能不是,但这取决于你的硬件” . 您可以查看:
根据这说明,您可能想要反转部分缓冲区 . 或者,Jon Skeet具有特定端转换器here(寻找EndianBitConverter) .
请注意,itaniums(例如)是big-endian . 大多数英特尔都是小端的 .
重新具体的UDP / IP ......?
您需要了解网络字节顺序以及CPU字节顺序 .
通常,对于TCP / UDP通信,您始终使用htons函数(和
ntohs
及其相关函数)将数据转换为网络字节顺序 .通常网络顺序是big-endian,但在这种情况下(由于某种原因!),comms是小端,所以这些功能不是很有用 . 这很重要,因为你不能假设他们已经实现的UDP通信遵循任何其他标准,如果你有一个大端架构,它也会让生活变得困难,因为你不能用
htons
包装所有内容,因为你应该:-(但是,如果您来自intel x86架构,那么您已经是little-endian,所以只需发送数据而不进行转换 .
如果您正在解析并且性能不重要,请考虑以下非常简单的代码:
我正在玩UDP Multicast中的打包数据,因为我注意到包头(Wireshark)中有错误,所以我需要重新排序UInt16八位字节,所以我做了这个:
对于UInt32,
这仅用于测试
从哪个输出: