AshNaz87
AshNaz87

Reputation: 434

How to manually convert an integer into an IP address in Ruby

Can anyone assist me in manually converting an integer into an IP address?

I understand the concept, but I am struggling to figure out the process; the number 631271850, has an IP address of '37.160.113.170'.

I know that an IP address is made up of four octets and the solution I have to manually converting an IP address into a number is:

def ip_to_num(ip_address)
  array = ip_address.split('.').map(&:to_i)
  ((array[0] * 2**24) + (array[1] * 2**16) + (array[2] * 2**8) + (array[3]))
end

To do the reverse is puzzling me. How do I convert it back?

Upvotes: 3

Views: 3703

Answers (3)

Azyrod
Azyrod

Reputation: 31

The IPAddr class already handles that

IPAddr.new(631271850, Socket::AF_INET).to_s
# "37.160.113.170"
IPAddr.new("37.160.113.170").to_i
# 631271850

Upvotes: 3

Derek Wright
Derek Wright

Reputation: 1492

An IP is just a 32-bit integer representing a 4-byte array:

[631271850].pack('N').unpack('CCCC').join('.')
=> "37.160.113.170"

Just for fun, another way to convert IP to int:

"37.160.113.170".split(".").map(&:to_i).pack('CCCC').unpack('N')[0]
=> 631271850

Upvotes: 9

tadman
tadman

Reputation: 211590

Converting an IPv4 address to a number is deceptively complex. The reference function is inet_aton which does all the conversions correctly. You can also do this in Ruby to explore the different formats:

require 'socket'

addrs = %w[
  1.2.3.4
  1.2.3
  1.2
  1
]

addrs.each do |addr|
  puts '%12s -> %08x' % [
    addr,
    Socket.sockaddr_in(0, addr)[4,4].unpack('L>')[0]
  ]
end

This yields the following output:

 1.2.3.4 -> 01020304
   1.2.3 -> 01020003
     1.2 -> 01000002
       1 -> 00000001

The case of 1.2.3 and 1.2 is perhaps surprising. The last value is presumed to be a 16-bit value and 24-bit value respectively. These are all valid IPv4 addresses, though.

If you're writing your own, be sure to handle those strange edge-cases.

Upvotes: 3

Related Questions