在允许我们通过UDP/IP控制硬件的文档中,我找到了以下片段:
在此通信协议中,DWORD为4字节数据,WORD为2字节数据,BYTE为单字节数据。存储格式为小端序,即4字节(32位)数据存储为:d7-d0,d15-d8,d23-d16,d31-d24;2字节(16位)数据存储为:d7-d0,d15-d8。
我想知道如何将其转换为C#? 我需要在发送之前进行转换吗?例如,如果我要发送32位整数或4个字符的字符串?
在允许我们通过UDP/IP控制硬件的文档中,我找到了以下片段:
在此通信协议中,DWORD为4字节数据,WORD为2字节数据,BYTE为单字节数据。存储格式为小端序,即4字节(32位)数据存储为:d7-d0,d15-d8,d23-d16,d31-d24;2字节(16位)数据存储为:d7-d0,d15-d8。
我想知道如何将其转换为C#? 我需要在发送之前进行转换吗?例如,如果我要发送32位整数或4个字符的字符串?
C#本身不定义字节序。但是,每当你进行字节转换时,你都在做出一个选择。然而,BitConverter类具有一个IsLittleEndian字段,告诉你它的行为方式,但是它不提供选择。BinaryReader/BinaryWriter同理。
我的MiscUtil库有一个EndianBitConverter类,允许你定义字节序;对于BinaryReader/Writer也有类似的类。很遗憾没有在线使用指南,但它们非常简单 :)
(EndianBitConverter还有一个常规BitConverter中不具备的功能,即原地执行字节数组中的转换。)
您还可以使用
IPAddress.NetworkToHostOrder(...)
简而言之,短整型、整型或长整型。
对于小端模式,简短的回答是“可能不需要,但这取决于你的硬件”。你可以使用以下命令进行检查:
在处理技术方面,小端模式和大端模式是指在多字节数据类型的存储方式中,高位字节是否存放在内存的低地址处的一种约定。在小端模式下,低位字节排放在内存的低地址端,而高位字节则排放在内存的高地址端。而大端模式与之相反。
原文中的内容解释了在小端模式下是否需要采取额外措施的问题,并提供了一个检查方法。
bool le = BitConverter.IsLittleEndian;
根据这里所说的内容,你可能需要反转你的缓冲区部分。或者,Jon Skeet在这里有特定的字节顺序转换器(请查找EndianBitConverter)。
请注意,Itanium(例如)是大端的。大多数Intel处理器是小端的。
关于具体的UDP/IP问题...?
通常在TCP/UDP通信中,您需要使用htons
函数(以及ntohs
和相关函数)将数据转换为网络字节顺序。
通常情况下,网络字节顺序是大端字节序,但在这种情况下(由于某种原因!),通信采用的是小端字节序,因此这些函数并不是非常有用。这很重要,因为您不能假设他们实现的UDP通信遵循任何其他标准,如果您拥有大端架构,那么生活会变得困难,因为您无法像应该做的那样使用htons
来封装所有内容 :-(
然而,如果您来自英特尔x86体系结构,则已经是小端字节序,因此只需发送未经转换的数据即可。
我正在尝试使用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}
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);