用Ruby确定基于IP的用户网段

时间:2015-03-19 23:32:41

标签: ruby arrays string

我有一个网段列表,希望我的网站根据用户的IP地址识别哪些网段用户连接。这样我就可以在我的网站上自动选择他们的位置,而不必手动选择。什么是好方法或决定这个?

到目前为止,我有以下内容。

要查找客户端IP地址:

local_ip = UDPSocket.open {|s| s.connect('64.233.187.99', 1); s.addr.last }

我的网络细分数组:

network_segments = [
{"name"=>"Site 1", "starting_address"=>"192.168.168.1", "ending_address"=>"192.168.175.254"},
{"name"=>"Site 2", "starting_address"=>"192.168.184.1", "ending_address"=>"192.168.191.254"},
{"name"=>"Site 3", "starting_address"=>"192.168.176.1", "ending_address"=>"192.168.183.254"}
]

我已尝试从IP中删除期间并循环浏览每个网段,以查看 local_ip 是否为> starting_address 和< ending_address ,但这似乎不准确。它应该只返回一个名称,并返回所有名称。

有没有更好的方法来查看local_ip是否在我的任何网段IP之间?

ip = local_ip.delete('.').to_i

network_segments.each do |seg|
   start_addr = seg['starting_address'].delete('.').to_i
   end_addr = seg['ending_address'].delete('.').to_i

    if ip > start_addr and ip < end_addr
      puts seg['name']
    end
end

2 个答案:

答案 0 :(得分:1)

使用IPAddr类(表示IP地址)而不是删除了点的字符串。 IPAddr提供了比较运算符,可以了解哪些地址大于/小于另一个地址。

require 'ipaddr'
# ...
local_ip = IPAddr.new(local_ip)
network_segments.each do |seg|
  if local_ip > IPAddr.new(seg['starting_address']) and local_ip < IPAddr.new(seg['ending_address'])
    puts seg['name']
  end
end

编辑:除了您的范围从1..254而不是0..255之外,您可以使用网络掩码范围实现检查,例如:

IPAddr.new("192.168.168.1/21").to_range.first.to_s       # => "192.168.168.0"
IPAddr.new("192.168.168.1/21").to_range.last.to_s       # => "192.168.175.255"
IPAddr.new("192.168.168.1/21").include?("192.168.170.1") # => true
IPAddr.new("192.168.168.1/21").include?("192.168.176.1") # => false

答案 1 :(得分:0)

请注意,IP地址在字典上不可比较(即字符串),请考虑使用standard IPAddr module

require 'ipaddr'

a1 = '10.1.1.1'
a2 = '2.1.1.1'
a1 < a2 # => true (nope!)

i1 = IPAddr.new(a1)
i2 = IPAddr.new(a2)
i1 < i2 # => false (ok)

另请注意,use && instead of and for boolean logic是普遍接受的最佳做法。