2010-08-19 47 views

回答

75
>> require "ipaddr" 
=> true 
>> low = IPAddr.new("62.0.0.0").to_i 
=> 1040187392 
>> high = IPAddr.new("62.255.255.255").to_i 
=> 1056964607 
>> ip = IPAddr.new("62.156.244.13").to_i 
=> 1050473485 
>> (low..high)===ip 
=> true 

如果您將得到網絡而不是開始和結束地址,那麼就更簡單了

>> net = IPAddr.new("62.0.0.0/8") 
=> #<IPAddr: IPv4:62.0.0.0/255.0.0.0> 
>> net===IPAddr.new("62.156.244.13") 
=> true 

IPAddr也將與IPv6地址一起工作

>> low = IPAddr.new('1::') 
=> #<IPAddr: IPv6:0001:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff> 
>> high = IPAddr.new('2::') 
=> #<IPAddr: IPv6:0002:0000:0000:0000:0000:0000:0000:0000/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff> 
>> (low..high)===IPAddr.new('1::1') 
=> true 
+6

雖然jdl的帖子太棒了,但這是最好的解決方案。不要重新發明輪子。 – 2010-08-19 11:38:15

+0

是的,我喜歡這個。我不知道這個圖書館是否存在。 – jdl 2010-08-19 13:20:02

+0

這是現貨!謝謝! – r2b2 2012-04-23 07:00:01

11

我會用this killer little function將IP地址轉換成整數,然後比較這些。

def ip_addr_in_range?(low, high, addr) 
    int_addr = numeric_ip(addr) 
    int_addr <= numeric_ip(high) && int_addr >= numeric_ip(low) 
end 

def numeric_ip(ip_str) 
    ip_str.split('.').inject(0) { |ip_num, part| (ip_num << 8) + part.to_i } 
end 

def test_ip_addr_in_range(low, high, addr, expected) 
    result = ip_addr_in_range?(low, high, addr) 
    puts "#{addr} #{(expected ? 'should' : 'should not')} be within #{low} and #{high}: #{(expected == result ? 'PASS' : 'FAIL')}" 
end 


test_ip_addr_in_range("192.168.0.0", "192.168.0.255", "192.168.0.200", true) 
test_ip_addr_in_range("192.168.0.0", "192.168.0.155", "192.168.0.200", false) 
test_ip_addr_in_range("192.168.0.0", "192.168.255.255", "192.168.100.200", true) 
test_ip_addr_in_range("192.168.0.0", "192.168.100.255", "192.168.150.200", false) 
test_ip_addr_in_range("192.168.255.255", "192.255.255.255", "192.200.100.100", true) 
test_ip_addr_in_range("192.168.255.255", "192.255.255.255", "192.100.100.100", false) 
test_ip_addr_in_range("192.168.255.255", "255.255.255.255", "200.200.100.100", true) 
test_ip_addr_in_range("192.168.255.255", "255.255.255.255", "180.100.100.100", false) 

$ ruby ip_range.rb 
192.168.0.200 should be within 192.168.0.0 and 192.168.0.255: PASS 
192.168.0.200 should not be within 192.168.0.0 and 192.168.0.155: PASS 
192.168.100.200 should be within 192.168.0.0 and 192.168.255.255: PASS 
192.168.150.200 should not be within 192.168.0.0 and 192.168.100.255: PASS 
192.200.100.100 should be within 192.168.255.255 and 192.255.255.255: PASS 
192.100.100.100 should not be within 192.168.255.255 and 192.255.255.255: PASS 
200.200.100.100 should be within 192.168.255.255 and 255.255.255.255: PASS 
180.100.100.100 should not be within 192.168.255.255 and 255.255.255.255: PASS 
+0

+1爲廣泛的答案包括。測試 – jhwist 2010-08-19 08:14:04

+0

好的答案,完整的測試套件,+1 – 2010-08-19 12:30:30

-7

不要讓它變得比它要難。

def check_ip(ip) 
    '62.0.0.0' < ip and ip < '62.255.255.255' 
end 

check_ip '62.156.244.13' #=> true 

編輯:或者,如果你使用的Rails /的ActiveSupport:

def check_ip(ip) 
    ip.starts_with? '62' 
end 

check_ip '62.156.244.13' #=> true 
+0

這是否意味着Ruby自動識別字符串中的IP地址? – deceze 2010-08-19 03:41:56

+2

檢查「10.0.0.2」在「10.0.0.1」和「10.0.0.10」之間時,您的方法失敗。 – jdl 2010-08-19 03:43:32

+2

@deceze不。他依靠字母順序,這隻能巧合地爲他選擇的數字起作用。 – jdl 2010-08-19 03:44:47

-1

JDL的answer是好的。我會讓in_range?運作一個班輪:

def ip_addr_in_range?(low, high, addr) 
    (numeric_ip(low) .. numeric_ip(high)) === numeric_ip(addr) 
end 
0

我更喜歡這種方式爲IP地址轉換爲整數的範圍比較:

# n_ip("192.1.1.23") will return the number 192001001023 
def n_ip(input) 
    input.split(".").collect{|p| p.rjust(3, "0")}.join.to_i 
end 

def ip_in_range?(from, to, given) 
    (n_ip(from)..n_ip(to).include?(n_ip(given)) 
end 

現在,您可以檢查該值如下:

>> ip_in_range?("192.168.0.0", "192.168.0.255","192.168.0.200") 
ip_in_range?("192.168.0.0", "192.168.0.255","192.168.0.200") 
=> true 
>> ip_in_range?("192.168.0.0", "192.168.0.255", "192.168.1.200") 
ip_in_range?("192.168.0.0", "192.168.0.255", "192.168.1.200") 
=> false 

返回的整數不是IP地址的32位表示。該邏輯將適用於所有有效的IP地址。

3

由JDL的回答啓發,但有一個範圍:

class String 
    def to_ip 
    split(".").inject(0) { |s, p| (s << 8) + p.to_i } 
    end 
end 

("62.0.0.0".to_ip.."62.255.255.255".to_ip).include?("62.156.244.13".to_ip) 
+0

令人敬畏的做法。 – ylluminate 2012-03-06 14:06:04