SameShirtEveryDay.com

Personal blog of the one called Alex Gorbatchev, from Toronto, Canada.

IP to integer (ip2int, int2ip)

Posted on May 25th, 2007 by Alex Gorbatchev. In Ruby. 9 comments!

When storing IP in a database, it’s much better to store them as integers rather than VARCHAR(15). Here’s a handy function to convert an IP string to integer and back.

# Converts an IP string to integer
def ip2int(ip)
  return 0 unless ip =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/

  v = ip.split('.').collect { |i| i.to_i }
  return (v[0] << 24) | (v[1] << 16) | (v[2] << 8 ) | (v[3]);
end

# Converts an integer to IP string... could be prettier
def int2ip(int)
  tmp = int.to_i
  parts = []

  3.times do |i|
    tmp = tmp / 256.0
    parts << (256 * (tmp - tmp.to_i)).to_i
  end

  parts << tmp.to_i
  parts.reverse.join('.')
end
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

9 comments.

  1. Hi,

    I just found your nice code. I start thinking about your comment a la “could be prettier”. Here is my little effort.

    Instead of “… 3.times … end” I use this:

    for i in 0..3
    parts > (8 * i)).to_s
    end

    The idea behind this is to bild a bit-mask
    (256 ** (i + 1) – 1)
    The second step is a binary AND, to exempt the relevant digits
    (tmp & …)
    and at least a binary shift back to the original position.
    >> (8 * i)

    If you use the code with a (mysql)-database you have to think about using a UNSIGNED INT column. It costs me one hour to figure out what’s going wrong with large ip-addresses.

    Greetings and thanks for your code.

    PapaBaer

  2. Shit, it filters HTML, one more trial:

    parts << ((tmp & (256 ** (i + 1) – 1)) >> (8 * i)).to_s

  3. Фигня однако получается

    >> ip = ‘192.168.79.45′
    => “192.168.79.45″
    >> ip =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => nil
    >> ip =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => nil
    >> ‘234.4566′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => nil
    >> return 0 unless ‘234.4566′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    LocalJumpError: unexpected return
    from (irb):11
    >> 0 unless ‘234.4566′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => 0
    >> 0 unless ‘234.45.66.67′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => 0
    >> ‘234.45.66.67′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => nil
    >> ‘45.66.67′ =~ /d{1,3}.d{1,3}.d{1,3}.d{1,3}/
    => nil

  4. Вот вроде решение подойдет
    >> (’45.66.67′ =~ /[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/).nil?
    => true
    >> (’345.45.66.67′ =~ /[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/).nil?
    => false

  5. You can also use the ipaddr library to do the conversion for you.

    require ‘ipaddr’

    intip = IPAddr.new(”1.1.1.1″).to_i
    => 16843009

    and the other way round:

    ip = IPAddr.new(16843009, Socket::AF_INET).to_s
    => “1.1.1.1″

  6. Andrew Barringer

    Probably best to use the iaddr lib but that takes all the fun out of it.

    Here’s some interesting hacks..

    For shortest data storage you could store as bytes and then get it back out with something like this.

    def ip2bytes(ip)
    v = ip.split(’.').collect { |i| i.to_i }
    return [(v[0]

  7. Andrew Barringer

    comment parser hacked up my prior post so.. maybe I’ll post a little at a time.

    def ip2bytes(ip)
    v = ip.split(’.').collect { |i| i.to_i }
    return [(v[0]

  8. Andrew Barringer

    Here’s some more..
    def bytes2ip(ip_bytes)
    ip_bytes.unpack(”C4″).join(”.”)
    end

    def int2ip(ip_bytes)
    [ip_bytes].pack(”N”).unpack(”C4″).join(”.”)
    end

  9. ktulhu

    Why not use IPAddr library?

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> , rel="nofollow" in use - no link dropping, no keywords or domains as names; do not spam, and do not advertise!

home
Subscribe to this blog Follow me on Twitter My bookmarks on Delicious My photography on Flickr