代码之家  ›  专栏  ›  技术社区  ›  GateKiller

如何将IPv4转换成整数?

  •  89
  • GateKiller  · 技术社区  · 15 年前

    我正在寻找一个函数,可以将标准IPv4地址转换为整数。如果功能与此相反,则可获得加分。

    21 回复  |  直到 11 年前
        1
  •  141
  •   Barry Kelly    15 年前

    32位无符号整数 IPv4地址。同时 IPAddress.Address

    例如,我的本地谷歌在 64.233.187.99 . 相当于:

    64*2^24 + 233*2^16 + 187*2^8 + 99
    = 1089059683
    

    事实上, http://1089059683/

    下面是一个测试程序来显示这两种转换,包括网络/主机字节交换:

    using System;
    using System.Net;
    
    class App
    {
        static long ToInt(string addr)
        {
            // careful of sign extension: convert to uint first;
            // unsigned NetworkToHostOrder ought to be provided.
            return (long) (uint) IPAddress.NetworkToHostOrder(
                 (int) IPAddress.Parse(addr).Address);
        }
    
        static string ToAddr(long address)
        {
            return IPAddress.Parse(address.ToString()).ToString();
            // This also works:
            // return new IPAddress((uint) IPAddress.HostToNetworkOrder(
            //    (int) address)).ToString();
        }
    
        static void Main()
        {
            Console.WriteLine(ToInt("64.233.187.99"));
            Console.WriteLine(ToAddr(1089059683));
        }
    }
    
        2
  •  43
  •   Saeb Amini    5 年前

    下面是一对从IPv4转换为 对的

    public static uint ConvertFromIpAddressToInteger(string ipAddress)
    {
        var address = IPAddress.Parse(ipAddress);
        byte[] bytes = address.GetAddressBytes();
    
        // flip big-endian(network order) to little-endian
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(bytes);
        }
    
        return BitConverter.ToUInt32(bytes, 0);
    }
    
    public static string ConvertFromIntegerToIpAddress(uint ipAddress)
    {
        byte[] bytes = BitConverter.GetBytes(ipAddress);
    
        // flip little-endian to big-endian(network order)
        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(bytes);
        }
    
        return new IPAddress(bytes).ToString();
    }
    

    例子

    ConvertFromIpAddressToInteger("255.255.255.254"); // 4294967294
    ConvertFromIntegerToIpAddress(4294967294); // 255.255.255.254
    

    解释

    int

    IPv4 内景 不能保存大于 127.255.255.255 (255.255.255.255) ,所以使用 uint

        3
  •  41
  •   Davy Landman    15 年前

    @巴里·凯利和@安德鲁·黑尔,事实上,我不认为乘法是实现这一目标的最明确的方法(alltough correct)。

    一个Int32“格式化”的IP地址可以看作是下面的结构

    [StructLayout(LayoutKind.Sequential, Pack = 1)] 
    struct IPv4Address
    {
       public Byte A;
       public Byte B;
       public Byte C;
       public Byte D;
    } 
    // to actually cast it from or to an int32 I think you 
    // need to reverse the fields due to little endian
    

    (64  = 0x40) << 24 == 0x40000000
    (233 = 0xE9) << 16 == 0x00E90000
    (187 = 0xBB) << 8  == 0x0000BB00
    (99  = 0x63)       == 0x00000063
                          ---------- =|
                          0x40E9BB63
    

    所以你可以用+把它们加起来,或者你可以把它们组合起来。生成0x40E9BB63,即1089059683。(在我看来,用十六进制来查看字节要容易得多)

    所以你可以把函数写成:

    int ipToInt(int first, int second, 
        int third, int fourth)
    {
        return (first << 24) | (second << 16) | (third << 8) | (fourth);
    }
    
        4
  •  12
  •   Rubens Farias    15 年前

    试试这个:

    private int IpToInt32(string ipAddress)
    {
       return BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(), 0);
    }
    
    private string Int32ToIp(int ipAddress)
    {
       return new IPAddress(BitConverter.GetBytes(ipAddress).Reverse().ToArray()).ToString();
    }
    
        5
  •  7
  •   Guffa    11 年前

    BitConverter 实际上,检查尾数,如下所示:

    byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray();
    if (BitConverter.IsLittleEndian) {
      Array.Reverse(ip);
    }
    int num = BitConverter.ToInt32(ip, 0);
    

    以及背面:

    byte[] ip = BitConverter.GetBytes(num);
    if (BitConverter.IsLittleEndian) {
      Array.Reverse(ip);
    }
    string address = String.Join(".", ip.Select(n => n.ToString()));
    
        6
  •  7
  •   avs099    4 年前

    用IP地址描述了我遇到的一些大问题的解决方法。 修复它对我来说,是一个简单的类型铸造操作。

    public static long ConvertIPToLong(string ipAddress)
    {
        System.Net.IPAddress ip;
    
        if (System.Net.IPAddress.TryParse(ipAddress, out ip))
        {
            byte[] bytes = ip.GetAddressBytes();
    
            return
                16777216L * bytes[0] +
                65536 * bytes[1] +
                256 * bytes[2] +
                bytes[3]
                ;
        }
        else
            return 0;
    }
    
        7
  •  4
  •   Noctis    10 年前

    string IntToIp(int d)
    {
      int v1 = d & 0xff;
      int v2 = (d >> 8) & 0xff;
      int v3 = (d >> 16) & 0xff;
      int v4 = (d >> 24);
      return v4 + "." + v3 + "." + v2 + "." + v1;
    }
    
        8
  •  3
  •   Noctis    10 年前

    我的问题结束了,我不知道为什么。这里接受的答案和我需要的不一样。

    public double IPAddressToNumber(string IPaddress)
    {
        int i;
        string [] arrDec;
        double num = 0;
        if (IPaddress == "")
        {
            return 0;
        }
        else
        {
            arrDec = IPaddress.Split('.');
            for(i = arrDec.Length - 1; i >= 0 ; i = i -1)
                {
                    num += ((int.Parse(arrDec[i])%256) * Math.Pow(256 ,(3 - i )));
                }
            return num;
        }
    }
    
        9
  •  2
  •   DanM7    11 年前

    对于正确的little-endian格式的UInt32,下面是两个简单的转换函数:

    public uint GetIpAsUInt32(string ipString)
    {
        IPAddress address = IPAddress.Parse(ipString);
    
        byte[] ipBytes = address.GetAddressBytes();
    
        Array.Reverse(ipBytes);
    
        return BitConverter.ToUInt32(ipBytes, 0);
    }
    
    public string GetIpAsString(uint ipVal)
    {
        byte[] ipBytes = BitConverter.GetBytes(ipVal);
    
        Array.Reverse(ipBytes);
    
        return new IPAddress(ipBytes).ToString();
    }
    
        10
  •  2
  •   Doug Clutter    9 年前

    将上述几个答案组合到一个扩展方法中,该方法处理计算机的Endianness并处理映射到IPv6的IPv4地址。

    public static class IPAddressExtensions
    {
        /// <summary>
        /// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer.
        /// </summary>
        /// <param name="address">The address to conver</param>
        /// <returns>An unsigned integer that represents an IPv4 address.</returns>
        public static uint ToUint(this IPAddress address)
        {
            if (address.AddressFamily == AddressFamily.InterNetwork || address.IsIPv4MappedToIPv6)
            {
                var bytes = address.GetAddressBytes();
                if (BitConverter.IsLittleEndian)
                    Array.Reverse(bytes);
    
                return BitConverter.ToUInt32(bytes, 0);
            }
            throw new ArgumentOutOfRangeException("address", "Address must be IPv4 or IPv4 mapped to IPv6");
        }
    }
    

    单元测试:

    [TestClass]
    public class IPAddressExtensionsTests
    {
        [TestMethod]
        public void SimpleIp1()
        {
            var ip = IPAddress.Parse("0.0.0.15");
            uint expected = GetExpected(0, 0, 0, 15);
            Assert.AreEqual(expected, ip.ToUint());
        }
        [TestMethod]
        public void SimpleIp2()
        {
            var ip = IPAddress.Parse("0.0.1.15");
            uint expected = GetExpected(0, 0, 1, 15);
            Assert.AreEqual(expected, ip.ToUint());
        }
        [TestMethod]
        public void SimpleIpSix1()
        {
            var ip = IPAddress.Parse("0.0.0.15").MapToIPv6();
            uint expected = GetExpected(0, 0, 0, 15);
            Assert.AreEqual(expected, ip.ToUint());
        }
        [TestMethod]
        public void SimpleIpSix2()
        {
            var ip = IPAddress.Parse("0.0.1.15").MapToIPv6();
            uint expected = GetExpected(0, 0, 1, 15);
            Assert.AreEqual(expected, ip.ToUint());
        }
        [TestMethod]
        public void HighBits()
        {
            var ip = IPAddress.Parse("200.12.1.15").MapToIPv6();
            uint expected = GetExpected(200, 12, 1, 15);
            Assert.AreEqual(expected, ip.ToUint());
        }
        uint GetExpected(uint a, uint b, uint c, uint d)
        {
            return
                (a * 256u * 256u * 256u) +
                (b * 256u * 256u) +
                (c * 256u) +
                (d);
        }
    }
    
        11
  •  1
  •   Andrew Hare    15 年前

    如果您对该功能感兴趣,那么这里的答案不仅仅是它是如何实现的:

    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);
    }
    

    具有 first 通过 fourth

        12
  •  1
  •   Noctis    10 年前
    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;
    }
    
        13
  •  1
  •   Gerard ONeill    10 年前
        public static Int32 getLongIPAddress(string ipAddress)
        {
            return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0));
        }
    

    上面的例子就是我的方法。。您可能需要做的唯一一件事是转换成UInt32以显示或字符串的目的,包括使用它作为字符串形式的长地址。

    这是使用IP地址。解析(字符串)函数。叹息。

        14
  •  0
  •   James Chambers James Chambers    15 年前

    我今天想出了一个解决方案(应该先在google上搜索!):

        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公司

        15
  •  0
  •   Marian Marian    15 年前

        16
  •  0
  •   Massimo    13 年前

    @Davy Ladman你用shift的解决方案是正确的,但仅对于ip开头的数字小于或等于99,事实上第一个八分之一必须投到long。

    无论如何,用long类型转换回是相当困难的,因为存储64位(而不是Ip的32位)并用0填充4个字节

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

    马西莫

        17
  •  0
  •   Andrew    10 年前

    假设您有一个字符串格式的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));
    
        18
  •  0
  •   xagyg    9 年前
    var ipAddress = "10.101.5.56";
    
    var longAddress = long.Parse(string.Join("", ipAddress.Split('.').Select(x => x.PadLeft(3, '0'))));
    
    Console.WriteLine(longAddress);
    

    输出:10101005056

        19
  •  0
  •   slavoo user3099232    8 年前
    var address = IPAddress.Parse("10.0.11.174").GetAddressBytes();
    long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF);
    
        20
  •  0
  •   Ondřej    5 年前

        21
  •  -1
  •   abelenky    15 年前

    看看.Net中的一些疯狂的解析示例IP地址。解析: MSDN


    “20.2”==>20.0.0.2
    “20.65535”==>20.0.255.255