代码之家  ›  专栏  ›  技术社区  ›  JP Silvashy Gautam Rege

Rails:找出IP是否在IP的范围内

  •  33
  • JP Silvashy Gautam Rege  · 技术社区  · 14 年前

    你怎么知道一个ip 62.156.244.13 在以下范围内 62.0.0.0 62.255.255.255

    7 回复  |  直到 5 年前
        1
  •  87
  •   Evan Appleby    8 年前
    >> 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
    
        2
  •  12
  •   Dave Powers    5 年前

    我会用 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
    
        3
  •  10
  •   Dmitrii    6 年前

    有一种方法 #include?

    你可以这样做:

    IPAddr.new("127.0.0.1/8").include? "127.1.10.200"

        4
  •  3
  •   Todd Yandell    14 年前

    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)
    
        5
  •  0
  •   Harish Shetty    14 年前

    我更喜欢这种将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地址。

        6
  •  -1
  •   Community CDub    7 年前

    jdl的 answer 很好。我会在你的范围内吗?功能一行:

    def ip_addr_in_range?(low, high, addr)
      (numeric_ip(low) .. numeric_ip(high)) === numeric_ip(addr)
    end
    
        7
  •  -7
  •   PreciousBodilyFluids    14 年前

    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