111

I'm looking for a function that will convert a standard IPv4 address into an Integer. Bonus points available for a function that will do the opposite.

Solution should be in C#.

Eric Leschinski
  • 123,728
  • 82
  • 382
  • 321
GateKiller
  • 68,419
  • 71
  • 167
  • 203
  • 16
    **WARNING**: the integers resulting from the accepted answer will be _wrong_, because IP addresses are in network order (big-endian), while `int`s are little-endian on most systems. So you must reverse the bytes before converting. See [my answer](http://stackoverflow.com/a/13350494/68080) for correct conversions. Also, even for IPv4, an `int` can't hold addresses bigger than `127.255.255.255`, _e.g._ the broadcast address, so use a `uint`. – Saeb Amini Nov 12 '12 at 20:00

22 Answers22

146

32-bit unsigned integers are IPv4 addresses. Meanwhile, the IPAddress.Address property, while deprecated, is an Int64 that returns the unsigned 32-bit value of the IPv4 address (the catch is, it's in network byte order, so you need to swap it around).

For example, my local google.com is at 64.233.187.99. That's equivalent to:

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

And indeed, http://1089059683/ works as expected (at least in Windows, tested with IE, Firefox and Chrome; doesn't work on iPhone though).

Here's a test program to show both conversions, including the network/host byte swapping:

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));
    }
}
Barry Kelly
  • 39,856
  • 4
  • 99
  • 180
  • 2
    Confirmed in Opera 11 on Ubuntu Linux 10.04: it converts the int back to the familiar w.x.y.z form, and It Works. – Piskvor left the building Dec 07 '10 at 15:21
  • 7
    IPAddress.Address is **obsolete** as of .Net 4.0. – Erik Philips Jul 16 '14 at 21:42
  • @ErikPhilips Does that matter if you only use IPv4? – Ray Oct 23 '14 at 20:41
  • That's an architectural decision. It has it's pros and cons, and comments are not the best location to discussion that specific issue. – Erik Philips Oct 23 '14 at 20:44
  • 2
    you may use BitConverter.ToUInt32(IPAddress.Parse(value).GetAddressBytes().Reverse().ToArray() to fix IPAddress.Address is obsolete – Mhmd May 28 '16 at 11:50
  • casting address to int isn't going to work for all address ... also the use of obsoleted methods and function doesn't make a good answer... – L.Trabacchin May 06 '18 at 07:42
  • @L.Trabacchin have a look at the date of the answer. It's an unfortunate fact that the whole internet won't change when a new release of software comes out... – Barry Kelly May 08 '18 at 09:58
  • @L.Trabacchin oh and casting to int will work for all long values in the range of a uint. Try it out. You might be surprised. Don't forget that the topic of the question is IPv4 - all addresses will be in the range of a uint. – Barry Kelly May 08 '18 at 10:04
  • @BarryKelly exactly the point of having a community. update answer, remove the ones not relevant anymore... Also i was referring to "(int) IPAddress.Parse(addr).Address" this is not casting to UInt, but Int, and lot of those address are out of int range – L.Trabacchin May 08 '18 at 16:28
  • IPv4 8bytes must use `ulong` – Mason.Chase Jan 19 '19 at 22:49
46

Here's a pair of methods to convert from IPv4 to a correct integer and back:

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

Example

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

Explanation

IP addresses are in network order (big-endian), while ints are little-endian on Windows, so to get a correct value, you must reverse the bytes before converting on a little-endian system.

Also, even for IPv4, an int can't hold addresses bigger than 127.255.255.255, e.g. the broadcast address (255.255.255.255), so use a uint.

Saeb Amini
  • 19,545
  • 8
  • 69
  • 71
  • This doesn't actually seem to make a difference on Windows using .NET - unsure about Mono. See https://dotnetfiddle.net/cBIOj2 – Jesse Mar 07 '18 at 12:42
  • 2
    @Jesse it happens to not make a difference for your input of `1.1.1.1` because its byte array is palindromic. Try with non-palindromic ones like `127.0.0.1` or `192.168.1.1`. – Saeb Amini Mar 07 '18 at 23:05
  • I see the issue. Repeated numbers such as `1.1.1.1`, `2.2.2.2`, `123.123.123.123` always yield the same result. For posterity, see updated fiddle: https://dotnetfiddle.net/aR6fhc – Jesse Mar 09 '18 at 18:30
  • Like to note that I had to use `System.Net.IPAddress` to get this working. Works great! – Shrout1 Apr 06 '18 at 20:45
  • 1
    @Jesse that wouldn't be just for repeating numbers, but for all [palindromic](https://en.wikipedia.org/wiki/Palindromic_number) IP addresses. So `2.1.1.2` would be the same. – Saeb Amini Jan 21 '19 at 22:49
42

@Barry Kelly and @Andrew Hare, actually, I don't think multiplying is the most clear way to do this (alltough correct).

An Int32 "formatted" IP address can be seen as the following structure

[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

So to convert the ip address 64.233.187.99 you could do:

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

so you could add them up using + or you could binairy or them together. Resulting in 0x40E9BB63 which is 1089059683. (In my opinion looking in hex it's much easier to see the bytes)

So you could write the function as:

int ipToInt(int first, int second, 
    int third, int fourth)
{
    return (first << 24) | (second << 16) | (third << 8) | (fourth);
}
Davy Landman
  • 14,421
  • 6
  • 46
  • 72
  • 1
    I believe that ip's were speced that way to specifically allow for such behavior... bit shifts are much more efficient on most microprocessors than muls and adds. – Ape-inago Jun 14 '09 at 05:46
  • 1
    @Ape-inago multiplications by constant powers of two are normally optimized into bit shifts, fwiw. – Barry Kelly Apr 30 '14 at 13:14
  • Instead of bit shifting, you can use `LayoutKind.Explicit` and `FieldOffset` to reverse the order in which the bytes are stored. Of course, that only works for little endian architecture. [Example on github](https://github.com/ckuhn203/Katas/blob/497e37b9a7d4854f44f08e734a7b71c7d2ef3eb6/Rubberduck.Katas.Network/Rubberduck.Katas.Network/Ip4Address.cs). – RubberDuck Nov 29 '15 at 12:16
  • 2
    Have to point out that `int` is signed so if you shift 192 by 24 bits you will get negative integer so this code is broken for high octet having high bit on first place. – Mateusz Feb 14 '19 at 15:21
12

Try this ones:

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();
}
Rubens Farias
  • 54,126
  • 8
  • 125
  • 158
  • [`Reverse()`](http://msdn.microsoft.com/en-us/library/d3877932(v=vs.110).aspx) returns void, so you cannot call `ToArray()` on it (for future readers). Instead, assign a value to the reversed bytes, then you can call ToArray(). – Erik Philips Jul 16 '14 at 21:46
  • 1
    [Reverse()](http://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx) is extension method of `IEnumerable`. Above code is perfectly ok. – Ant Nov 12 '14 at 10:04
  • 3
    This method yields negative numbers for certain IPs (e.g. 140.117.0.0) – lightxx Jan 26 '15 at 09:13
8

I have encountered some problems with the described solutions, when facing IP Adresses with a very large value. The result would be, that the byte[0] * 16777216 thingy would overflow and become a negative int value. what fixed it for me, is the a simple type casting operation.

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;
}
avs099
  • 10,000
  • 5
  • 53
  • 105
Qiong Wu
  • 1,124
  • 1
  • 12
  • 19
7

As noone posted the code that uses BitConverter and actually checks the endianness, here goes:

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

and back:

byte[] ip = BitConverter.GetBytes(num);
if (BitConverter.IsLittleEndian) {
  Array.Reverse(ip);
}
string address = String.Join(".", ip.Select(n => n.ToString()));
Guffa
  • 640,220
  • 96
  • 678
  • 956
  • 2
    You need to use a uint, but this is the most correct answer here. – RubberDuck Nov 29 '15 at 12:22
  • 1
    @RubberDuck: You only need to use an `uint` if you want the 32 bits of data as an unsigned number, an `int` is capable of holding the same information. If you want to store it in a database an `int` is better suited, you need a `bigint` to be able to store it in the unsigned form. – Guffa Nov 29 '15 at 12:32
  • 1
    A uint is a better representation IMO. A signed int needs a bit for the sign, so you lose addresses at the very top of the range. Yes, it can hold the same data, but it will be output as a negative number, which isn't a valid IP if you type it in the address bar. – RubberDuck Nov 29 '15 at 12:36
  • @RubberDuck: In the form of an `uint` you can't type it in the address bar either, you first have to convert it into text form to do that. Just because using the simplest form of turning an `int` into text doesn't produce a working IP address is not a good argument for not using it. – Guffa Nov 29 '15 at 12:58
  • @RubberDuck: That's not an `uint`, that's the text representation of an `uint`. – Guffa Nov 29 '15 at 13:08
4

The reverse of Davy Landman's function

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;
}
Noctis
  • 10,865
  • 3
  • 38
  • 74
3

My question was closed, I have no idea why . The accepted answer here is not the same as what I need.

This gives me the correct integer value for an IP..

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;
    }
}
Noctis
  • 10,865
  • 3
  • 38
  • 74
Coolcoder
  • 3,966
  • 5
  • 25
  • 34
  • As long as you can do the conversion both way, I don't see why the output number has to be correct just as long as it's consistent. – GateKiller Jan 22 '09 at 11:22
  • Depends on what you want to use the number for. You cant use the other conversion for doing a >= and <= query to find an IP.. – Coolcoder Jan 22 '09 at 11:26
2

With the UInt32 in the proper little-endian format, here are two simple conversion functions:

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();
}
DanM7
  • 2,101
  • 3
  • 25
  • 45
2
    public static Int32 getLongIPAddress(string ipAddress)
    {
        return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0));
    }

The above example would be the way I go.. Only thing you might have to do is convert to a UInt32 for display purposes, or string purposes including using it as a long address in string form.

Which is what is needed when using the IPAddress.Parse(String) function. Sigh.

Gerard ONeill
  • 3,193
  • 31
  • 22
2

Assembled several of the above answers into an extension method that handles the Endianness of the machine and handles IPv4 addresses that were mapped to IPv6.

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

Unit tests:

[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);
    }
}
Doug Clutter
  • 3,392
  • 2
  • 25
  • 26
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;
}
Noctis
  • 10,865
  • 3
  • 38
  • 74
xadd
  • 19
  • 1
1

If you were interested in the function not just the answer here is how it is done:

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

with first through fourth being the segments of the IPv4 address.

Andrew Hare
  • 320,708
  • 66
  • 621
  • 623
1

Multiply all the parts of the IP number by powers of 256 (256x256x256, 256x256, 256 and 1. For example:

IPv4 address : 127.0.0.1 32 bit number: = (127x256^3) + (0x256^2) + (0x256^1) + 1 = 2130706433

  • This is the most simple and elegant solution, imho. You could put it in C++ code, though, for this is what the op requested :) – karlsebal Apr 19 '21 at 16:34
0

Assuming you have an IP Address in string format (eg. 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));
Andrew
  • 1
0
var ipAddress = "10.101.5.56";

var longAddress = long.Parse(string.Join("", ipAddress.Split('.').Select(x => x.PadLeft(3, '0'))));

Console.WriteLine(longAddress);

Output: 10101005056

xagyg
  • 8,908
  • 2
  • 26
  • 27
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);
slavoo
  • 4,967
  • 63
  • 33
  • 38
shzy2012
  • 1
  • 1
  • the GetAddressBytes method may returns the bytes in the reverse order, depending if the machine is endian or endian-ness so the correct statement may be for some machines: long m_Address = (address[0] << 24 | address[1] << 16 | address[2] << 8 | address[3]) & 0x0FFFFFFFF – MiguelSlv May 06 '16 at 23:08
0

@Davy Ladman your solution with shift are corrent but only for ip starting with number less or equal 99, infact first octect must be cast up to long.

Anyway convert back with long type is quite difficult because store 64 bit (not 32 for Ip) and fill 4 bytes with zeroes

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

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

Enjoy!

Massimo

Massimo
  • 9
  • 1
0

I noticed that System.Net.IPAddress have Address property (System.Int64) and constructor, which also accept Int64 data type. So you can use this to convert IP address to/from numeric (although not Int32, but Int64) format.

Ondřej
  • 1,538
  • 1
  • 16
  • 26
0

here's a solution that I worked out today (should've googled first!):

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

i'm using LINQ, lambda and some of the extensions on generics, so while it produces the same result it uses some of the new language features and you can do it in three lines of code.

i have the explanation on my blog if you're interested.

cheers, -jc

0

I think this is wrong: "65536" ==> 0.0.255.255" Should be: "65535" ==> 0.0.255.255" or "65536" ==> 0.1.0.0"

-1

Take a look at some of the crazy parsing examples in .Net's IPAddress.Parse: (MSDN)

"65536" ==> 0.0.255.255
"20.2" ==> 20.0.0.2
"20.65535" ==> 20.0.255.255
"128.1.2" ==> 128.1.0.2

abelenky
  • 58,532
  • 22
  • 99
  • 149