如何在C#中将IPv4地址转换为整数?

118
我正在寻找一个函数,可以将标准IPv4地址转换为整数。如果函数能够实现反向转换,则可获得额外积分。解决方案应使用C#编写。

18
警告:接受的答案所产生的整数将是“错误”的,因为IP地址是按网络字节序(大端序)排列的,而大多数系统中的int是小端序。因此,在转换之前必须颠倒字节顺序。请参见我的答案以获取正确的转换方式。即使对于IPv4,一个int也无法容纳大于127.255.255.255的地址,例如广播地址,因此请使用uint - Saeb Amini
@SaebAmini我的答案使用NetworkToHostOrder来反转字节。且int可以包含大于127.255.255.255的地址;它们以负数形式存储。当将类型转换为int时,Address属性中大于2^31的数字,即long类型,会变成负数;将其转换为int是为了调用NetworkToHostOrder,并且不会截断数字。 - Barry Kelly
22个回答

2
    public static Int32 getLongIPAddress(string ipAddress)
    {
        return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0));
    }

以上示例是我所采用的方式。唯一需要做的事情可能是将其转换为UInt32以便于显示,或者转换为字符串,包括在字符串形式下使用它作为长地址。

这就是在使用IPAddress.Parse(String)函数时所需的。哎。


1

将IP地址的所有部分乘以256的幂次方(256x256x256,256x256,256和1)。例如:

IPv4地址:127.0.0.1 32位数字: = (127x256^3)+(0x256^2)+(0x256^1)+1 = 2130706433


这是我认为最简单和优雅的解决方案。尽管如此,你可以将其放入C++代码中,因为这是op所请求的 :) - karlsebal

1
如果您对函数本身感兴趣而不仅仅是答案,那么这就是它的实现方式:
int ipToInt(int first, int second, 
    int third, int fourth)
{
    return Convert.ToInt32((first * Math.Pow(256, 3))
        + (second * Math.Pow(256, 2)) + (third * 256) + fourth);
}

firstfourth 是 IPv4 地址的四个段。


1
如果你使用 shift 而不是 Math.Pow,我认为会更清晰明了。 - Mehrdad Afshari
如果first > 127,这将抛出一个溢出异常。Davy Landman的答案是实现此操作的最佳方式。 - mhenry1384
int32是有符号的,因此它将返回第一个八位字节大于127的负值。 - Mateusz

1
public bool TryParseIPv4Address(string value, out uint result)
{
    IPAddress ipAddress;

    if (!IPAddress.TryParse(value, out ipAddress) ||
        (ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork))
    {
        result = 0;
        return false;
    }

    result = BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(), 0);
    return true;
}

0

@Davy Ladman,你的解决方案使用移位是正确的,但仅适用于以数字小于或等于99开头的IP地址。实际上,第一个八位组必须转换为长整型。

无论如何,使用长整型进行转换相当困难,因为它需要存储64位(而不是32位),并用零填充4个字节。

static uint ToInt(string addr)
{
   return BitConverter.ToUInt32(IPAddress.Parse(addr).GetAddressBytes(), 0);
}

static string ToAddr(uint address)
{
    return new IPAddress(address).ToString();
}

享受吧!

马西莫


0
var address = IPAddress.Parse("10.0.11.174").GetAddressBytes();
long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF);

GetAddressBytes 方法可能会根据机器的大小端或字节序以相反顺序返回字节,因此对于某些机器,正确的语句可能是:long m_Address = (address[0] << 24 | address[1] << 16 | address[2] << 8 | address[3]) & 0x0FFFFFFFF - MiguelSlv

0
我使用这个:
public static uint IpToUInt32(string ip)
{
    if (!IPAddress.TryParse(ip, out IPAddress address)) return 0;
    return BitConverter.ToUInt32(address.GetAddressBytes(), 0);
}

public static string UInt32ToIp(uint address)
{
    return new IPAddress(address).ToString();
}

0
我认为这是错误的:"65536" ==> 0.0.255.255",应该是:"65535" ==> 0.0.255.255" 或者 "65536" ==> 0.1.0.0"。

0

这是我今天想出来的一个解决方案(应该先谷歌一下!):

    private static string IpToDecimal2(string ipAddress)
    {
        // need a shift counter
        int shift = 3;

        // loop through the octets and compute the decimal version
        var octets = ipAddress.Split('.').Select(p => long.Parse(p));
        return octets.Aggregate(0L, (total, octet) => (total + (octet << (shift-- * 8)))).ToString();
    }

我正在使用LINQ、Lambda和一些泛型扩展,虽然它产生了相同的结果,但它使用了一些新的语言特性,你可以用三行代码完成。

如果您感兴趣,我在我的博客上有解释。

祝好, -jc


0
假设您有一个以字符串格式表示的IP地址(例如254.254.254.254)。
string[] vals = inVal.Split('.');
uint output = 0;
for (byte i = 0; i < vals.Length; i++) output += (uint)(byte.Parse(vals[i]) << 8 * (vals.GetUpperBound(0) - i));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接