C# BitConverter.GetBytes() 填充不正确?

C# BitConverter.GetBytes() padding is incorrect?

我正致力于在 .net 核心中编写自己的 DNS 服务器。我正处于对响应有效负载进行编码以发回的阶段,架构显示大多数数字都编码为 16 位数字。 C# 的整数是 32 位数字。没什么大不了的,我只是去掉数字前面剩余的 16 位,我对此没有问题。

在我发现 System.BitConverter class 之前,我一直在手动执行此操作。然而,我尝试使用它,但我得出的结果与它得出的结果相反。

例如:

using System;
                    
var myInt = 15;

byte[] data = new byte[2];

data[0] = (byte)(myInt >> 8);
data[1] = (byte)(myInt & 255);

var myIntStr = "";

foreach(var b in data)
{
    myIntStr += System.Convert.ToHexString(new byte[]{ b });
    myIntStr += " ";
}

Console.WriteLine(myIntStr);

var myShort = System.Convert.ToInt16(myInt);

byte[] data2 = System.BitConverter.GetBytes(myShort);

myIntStr = "";

foreach(var b in data2)
{
    myIntStr += System.Convert.ToHexString(new byte[]{ b });
    myIntStr += " ";
}

Console.WriteLine(myIntStr);

此代码产生以下结果:

00 0F 
0F 00 

我的理解是 000F 是 15,而 0F00 是 3840。我没有正确理解位移位吗?从字面上看,我昨晚才开始使用实际位大声笑。

感谢阅读本文并提前感谢您的帮助!

根据对问题的评论,答案在于字节顺序。

从我用来测试的 dig 命令发送的网络字节顺序使用 Big Endian 顺序。但是,我的 CPU 体系结构是 Small Endian。

Dotnet 在他们的 UDPClient 幕后 class 如果您的系统在发送字节时是 Small Endian,则反转字节,在接收字节时反之亦然。但是因为我是使用 Big Endian 格式的位移位手动创建字节,所以它们随后被反转为非网络字节顺序,而其他所有内容都是网络字节顺序。

此处的解决方案是使用条件逻辑来测试您的系统是否 IsLittleEndian According to the Microsoft dotnet docs,或者让 System.BitConverter class 为您处理。

例如:在我上面的示例中,我试图将 32 位 int 转换为 16 位无符号位。我最终将上面的代码替换为:

    public static byte[] IntTo16Bit(int input)
    {
        ushort input16;
        if (!UInt16.TryParse(input.ToString(), out input16))
        {
            throw new Exception($"Input was {input}");
        }
        if (BitConverter.IsLittleEndian)
        {
            return BitConverter.GetBytes(input16).Reverse().ToArray();
        }
        return BitConverter.GetBytes(input16);
    }

并计划在 i32 无法转换为 u16 时更好地处理。