将十六进制值解析为IPAddress C时的long.Parse和新IPAddress行为

时间:2014-11-07 11:29:14

标签: c# parsing ip-address

我昨天问了一个关于将HEX字符串转换为IP的问题并得到了答案:C# convert hex into ip

当我使用函数

时,问题是
var ip = new IPAddress(long.Parse(ipString, NumberStyles.AllowHexSpecifier));

它会返回一个有效的IPAddress,但会以相反的方式执行。例如:

十六进制字符串:

c0a8000a

并且应该解析为:

192.168.0.10

long.Parse()函数返回

3232235530

但是在调用IPAddress构造函数后我的IP是

10.0.168.192 

而不是正确的。像http://www.smartconversion.com/unit_conversion/IP_Address_Converter.aspx这样的在线工具运行正常。这是一个有点或大端的东西?我是否必须自己翻转字符串或者是否有更简单的答案?

3 个答案:

答案 0 :(得分:2)

所以你做了一点研究,你猜对了。它与字节序有关。

构造函数:IPAddress(long newAddress)期望值在network byte order中,并定义为 big-endian

我假设您的系统架构使用 little-endian (正如大多数英特尔系统那样)

.NET使用底层系统的字节序,因此当您在这样的系统上解析long时,它会存储为little-endian。

这就是为什么当您通过IPAddress.Parse解析整数 string 时,结果是正确的。


至于解决方案。

您可以解析IPAddress(按字符串):

IPAddress ip = IPAddress.Parse(uint.Parse(ipString, NumberStyles.AllowHexSpecifier).ToString());

或者为了更加“正确”,您可以检查BitConverter.IsLittleEndian字段并在nescessery中翻转字节顺序:

    static IPAddress ParseHexIPAddress(String szIPAddress) {
        uint uiIP = uint.Parse(szIPAddress, System.Globalization.NumberStyles.AllowHexSpecifier);
        IPAddress ip = null;
        if (BitConverter.IsLittleEndian) {
            uint uiIPRev = BitConverter.ToUInt32(BitConverter.GetBytes(uiIP).Reverse().ToArray(), 0);
            ip = new IPAddress(uiIPRev);
        } else {
            ip = new IPAddress(uiIP);
        }
        return ip;
    }

答案 1 :(得分:0)

默认情况下,数字(在您的情况下为long)以Little Endian格式存储在x86体系结构的内存中,这就是您将IP地址反转的原因。您可以在 BitConverter.IsLittleEndian 字段的帮助下查看此信息。一个简单的解决方案是反转输入字符串的字节顺序,然后将反转的字符串解析为如下所示:

string ipString = "c0a8000a";

// Reverse the HEX string byte order
int length = ipString.Length;
char[] reversedChars = new char[length];
for (int i = 0; i < length; i += 2)
{
    reversedChars[i] = ipString[length - i - 2];
    reversedChars[i + 1] = ipString[length - i - 1];
}

string reversedString = new string(reversedChars);

// Parse the reversed byte string
long parsedValue = long.Parse(reversedString, NumberStyles.AllowHexSpecifier);
IPAddress ip = new IPAddress(parsedValue);

答案 2 :(得分:0)

正如已经指出的那样,问题是你必须从主机字节顺序(litte endian)转换为网络字节顺序(big endian)。您可以使用IPAddress.HostToNetworkOrder方法执行此操作:

var ip = new IPAddress(
  IPAddress.HostToNetworkOrder(
    int.Parse(ipString, NumberStyles.AllowHexSpecifier)
  )
);

请注意,您需要使用int.Parse而不是long.Parse来实现此功能,因为IPv4地址是32位,而不是64位。

此方法不涉及字符串转换或使用其他类(如BitConverter)来执行转换。