我有一个网段列表,希望我的网站根据用户的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
答案 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是普遍接受的最佳做法。