27

我正在尝试将两个字节转换为无符号短字节,以便检索实际的服务器端口值。我将它基于回复格式下的这个协议规范。我尝试为此使用BitConverter.ToUint16(),但问题是,它似乎没有抛出预期值。请参阅下面的示例实现:

int bytesRead = 0;

while (bytesRead < ms.Length)
{
    int first = ms.ReadByte() & 0xFF;
    int second = ms.ReadByte() & 0xFF;
    int third = ms.ReadByte() & 0xFF;
    int fourth = ms.ReadByte() & 0xFF;
    int port1 = ms.ReadByte();
    int port2 = ms.ReadByte();
    int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
    string ip = String.Format("{0}.{1}.{2}.{3}:{4}-{5} = {6}", first, second, third, fourth, port1, port2, actualPort);
    Debug.WriteLine(ip);
    bytesRead += 6;
}

给定一个示例数据,假设对于两个字节值,我有 105 和 135,转换后的预期端口值应该是 27015,但我使用 BitConverter 得到的值是 34665。

我做错了吗?

4

3 回答 3

32

如果您反转 BitConverter 调用中的值,您应该得到预期的结果:

int actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);

在 little-endian 架构上,低位字节需要在数组中排在第二位。正如 lasseespeholt 在评论中指出的那样,您需要在大端架构上颠倒顺序。这可以通过BitConverter.IsLittleEndian属性进行检查。或者,总体上使用IPAddress.HostToNetworkOrder可能是一个更好的解决方案(首先转换值,然后调用该方法以正确的顺序放置字节,而不考虑字节序)。

于 2011-04-21T21:14:59.963 回答
13

BitConverter is doing the right thing, you just have low-byte and high-byte mixed up - you can verify using a bitshift manually:

byte port1 = 105;
byte port2 = 135;

ushort value = BitConverter.ToUInt16(new byte[2] { (byte)port1, (byte)port2 }, 0);
ushort value2 = (ushort)(port1 + (port2 << 8)); //same output
于 2011-04-21T21:16:34.647 回答
10

要同时处理小端和大端架构,您必须执行以下操作:

if (BitConverter.IsLittleEndian)
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port2 , (byte)port1 }, 0);
else
    actualPort = BitConverter.ToUInt16(new byte[2] {(byte)port1 , (byte)port2 }, 0);
于 2011-04-21T21:21:57.297 回答