Java 验证IP地址(带掩码)

Java 验证IP地址(带掩码),java,grails,groovy,Java,Grails,Groovy,我有ip地址和掩码,如10.1.1.1/32。我想检查10.1.1.1是否在该范围内。是否有库或实用程序可以这样做,或者我需要自己编写一些东西?首先,您需要将IP地址转换为平面ints,这将更易于使用: String s=“10.1.1.99”; Inet4Address a=(Inet4Address)InetAddress.getByName; 字节[]b=a.getAddress(); inti=((b[0]&0xFF)多亏了John Kugelman——我用他的代码片段创建了这个类 pa

我有ip地址和掩码,如
10.1.1.1/32
。我想检查
10.1.1.1
是否在该范围内。是否有库或实用程序可以这样做,或者我需要自己编写一些东西?

首先,您需要将IP地址转换为平面
int
s,这将更易于使用:

String s=“10.1.1.99”;
Inet4Address a=(Inet4Address)InetAddress.getByName;
字节[]b=a.getAddress();
inti=((b[0]&0xFF)多亏了John Kugelman——我用他的代码片段创建了这个类

package bs;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Represents an IP range based on an address/mask.
 * @author Scott Plante, using code snippets by John Kugelman.
 */
public class IPMask
{
  public static void main(String args[]) 
      throws UnknownHostException
  {
    IPMask ipmask;

    ipmask = IPMask.getIPMask("192.168.20.32/24");
    System.out.println("Checking "+ipmask+"...");

    test(ipmask, "192.168.20.31 ", true);
    test(ipmask, "192.168.20.32 ", true);
    test(ipmask, "192.168.20.33 ", true);
    test(ipmask, "192.168.20.34 ", true);
    test(ipmask, "192.168.20.35 ", true);
    test(ipmask, "192.168.20.36 ", true);
    test(ipmask, "192.168.20.254", true);
    test(ipmask, "192.168.20.157", true);
    test(ipmask, "192.168.21.1  ", false);
    test(ipmask, "192.168.19.255", false);
    test(ipmask, "192.168.24.1  ", false);

    ipmask = IPMask.getIPMask("192.168.20.32/31");
    System.out.println("Checking "+ipmask+"...");

    test(ipmask, "192.168.20.31 ", false);
    test(ipmask, "192.168.20.32 ", true);
    test(ipmask, "192.168.20.33 ", true);
    test(ipmask, "192.168.20.34 ", false);
    test(ipmask, "192.168.20.35 ", false);
    test(ipmask, "192.168.20.36 ", false);
    test(ipmask, "192.168.20.254", false);
    test(ipmask, "192.168.20.157", false);
    test(ipmask, "192.168.21.1  ", false);
    test(ipmask, "192.168.19.255", false);
    test(ipmask, "192.168.24.1  ", false);

    ipmask = IPMask.getIPMask("192.168.20.32/23");
    System.out.println("Checking "+ipmask+"...");

    test(ipmask, "192.168.20.31 ", true);
    test(ipmask, "192.168.20.32 ", true);
    test(ipmask, "192.168.20.33 ", true);
    test(ipmask, "192.168.20.254", true);
    test(ipmask, "192.168.21.254", true);
    test(ipmask, "192.168.19.255", false);
    test(ipmask, "192.168.24.1  ", false);

  }

  public static void test(IPMask ipmask, String addr, boolean expect) 
      throws UnknownHostException
  {
    boolean got = ipmask.matches(addr);
    System.out.println(addr + "\t(" + expect + ") ?\t"+got
        + "\t" + (got==expect?"":"!!!!!!!!"));
  }

  private Inet4Address i4addr;
  private byte maskCtr;

  private int addrInt;
  private int maskInt;

  public IPMask(Inet4Address i4addr, byte mask)
  {
    this.i4addr = i4addr;
    this.maskCtr = mask;

    this.addrInt = addrToInt(i4addr);
    this.maskInt = ~((1 << (32 - maskCtr)) - 1);
  }

  /** IPMask factory method. 
   * 
   * @param addrSlashMask IP/Mask String in format "nnn.nnn.nnn.nnn/mask". If 
   *    the "/mask" is omitted, "/32" (just the single address) is assumed.
   * @return a new IPMask
   * @throws UnknownHostException if address part cannot be parsed by 
   *    InetAddress
   */
  public static IPMask getIPMask(String addrSlashMask) 
      throws UnknownHostException
  {
    int pos = addrSlashMask.indexOf('/');
    String addr;
    byte maskCtr;
    if (pos==-1)
    {
      addr = addrSlashMask;
      maskCtr = 32;
    }
    else
    { 
      addr = addrSlashMask.substring(0, pos);
      maskCtr = Byte.parseByte(addrSlashMask.substring(pos + 1));
    }
    return new IPMask((Inet4Address) InetAddress.getByName(addr), maskCtr);
  }

 /** Test given IPv4 address against this IPMask object.
   * 
   * @param testAddr address to check.
   * @return true if address is in the IP Mask range, false if not.
   */  
  public boolean matches(Inet4Address testAddr)
  {
    int testAddrInt = addrToInt(testAddr);   
    return ((addrInt & maskInt) == (testAddrInt & maskInt));
  }

/** Convenience method that converts String host to IPv4 address.
   * 
   * @param addr IP address to match in nnn.nnn.nnn.nnn format or hostname.
   * @return true if address is in the IP Mask range, false if not.
   * @throws UnknownHostException if the string cannot be decoded.
   */
  public boolean matches(String addr) 
      throws UnknownHostException
  {
    return matches((Inet4Address)InetAddress.getByName(addr));
  }

/** Converts IPv4 address to integer representation.
   */
  private static int addrToInt(Inet4Address i4addr)
  {
    byte[] ba = i4addr.getAddress();  
    return (ba[0]       << 24) 
        | ((ba[1]&0xFF) << 16) 
        | ((ba[2]&0xFF) << 8) 
        |  (ba[3]&0xFF);
  }

  @Override
  public String toString()
  {
    return "IPMask(" + i4addr.getHostAddress() + "/" + maskCtr + ")";
  }

  @Override
  public boolean equals(Object obj)
  {
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    final IPMask that = (IPMask) obj;    
    return (this.addrInt == that.addrInt && this.maskInt == that.maskInt);
  }

  @Override
  public int hashCode()
  {
    return this.maskInt + this.addrInt;
  }

}
在我的系统上:

$> uname -a
Linux guin 2.6.37.6-0.5-desktop #1 SMP PREEMPT 2011-04-25 21:48:33 +0200 x86_64 x86_64 x86_64 GNU/Linux
$> java -version
java version "1.6.0_25"
Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b11, mixed mode)
$> 
您可以从上面的类中删除main和test方法。它们是从单元测试代码改编的,为了简单起见添加到这里。

public static boolean netMatch(String addr,String addr1){//addr是子网地址,addr1是ip地址。如果addr1在addr(subnet)内,函数将返回true
public static boolean netMatch(String addr, String addr1){ //addr is subnet address and addr1 is ip address. Function will return true, if addr1 is within addr(subnet)

        String[] parts = addr.split("/");
        String ip = parts[0];
        int prefix;

        if (parts.length < 2) {
            prefix = 0;
        } else {
            prefix = Integer.parseInt(parts[1]);
        }

        Inet4Address a =null;
        Inet4Address a1 =null;
        try {
            a = (Inet4Address) InetAddress.getByName(ip);
            a1 = (Inet4Address) InetAddress.getByName(addr1);
        } catch (UnknownHostException e){}

        byte[] b = a.getAddress();
        int ipInt = ((b[0] & 0xFF) << 24) |
                         ((b[1] & 0xFF) << 16) |
                         ((b[2] & 0xFF) << 8)  |
                         ((b[3] & 0xFF) << 0);

        byte[] b1 = a1.getAddress();
        int ipInt1 = ((b1[0] & 0xFF) << 24) |
                         ((b1[1] & 0xFF) << 16) |
                         ((b1[2] & 0xFF) << 8)  |
                         ((b1[3] & 0xFF) << 0);

        int mask = ~((1 << (32 - prefix)) - 1);

        if ((ipInt & mask) == (ipInt1 & mask)) {
            return true;
        }
        else {
            return false;
        }
}
String[]parts=addr.split(“/”); 字符串ip=部件[0]; int前缀; 如果(零件长度<2){ 前缀=0; }否则{ 前缀=整数.parseInt(部分[1]); } Inet4Address a=null; INET4AddressA1=null; 试一试{ a=(Inet4Address)InetAddress.getByName(ip); a1=(Inet4Address)InetAddress.getByName(addr1); }捕获(未知后异常e){} 字节[]b=a.getAddress();
int ipInt=((b[0]&0xFF)这是一个版本,它以几种常见的方式获取子网描述,包括IPv6

基于这里发布的其他代码。 在IPv4地址上,它可能比在裸
int
上执行二进制操作的方法工作得慢

package de.c3oe.tryanderror;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann
 */
public class Subnet
{
    final private int bytesSubnetCount;
    final private BigInteger bigMask;
    final private BigInteger bigSubnetMasked;

    /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */
    public Subnet( final InetAddress subnetAddress, final int bits )
    {
        this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
        this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits
        this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
    }

    /** For use via format "192.168.0.0/255.255.255.0" or single address */
    public Subnet( final InetAddress subnetAddress, final InetAddress mask )
    {
        this.bytesSubnetCount = subnetAddress.getAddress().length;
        this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here.
        this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
    }

    /**
     * Subnet factory method.
     * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
     *      or single address or "2001:db8:85a3:880:0:0:0:0/57"
     * @return a new instance
     * @throws UnknownHostException thrown if unsupported subnet mask.
     */
    public static Subnet createInstance( final String subnetMask )
            throws UnknownHostException
    {
        final String[] stringArr = subnetMask.split("/");
        if ( 2 > stringArr.length )
            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), (InetAddress)null );
        else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") )
            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) );
        else
            return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) );
    }

    public boolean isInNet( final InetAddress address )
    {
        final byte[] bytesAddress = address.getAddress();
        if ( this.bytesSubnetCount != bytesAddress.length )
            return false;
        final BigInteger bigAddress = new BigInteger( bytesAddress );
        return  bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked );
    }

    @Override
    final public boolean equals( Object obj )
    {
        if ( ! (obj instanceof Subnet) )
            return false;
        final Subnet other = (Subnet)obj;
        return  this.bigSubnetMasked.equals( other.bigSubnetMasked ) &&
                this.bigMask.equals( other.bigMask ) &&
                this.bytesSubnetCount == other.bytesSubnetCount;
    }

    @Override
    final public int hashCode()
    {
        return this.bytesSubnetCount;
    }

    @Override
    public String toString()
    {
        final StringBuilder buf = new StringBuilder();
        bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount );
        buf.append( '/' );
        bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount );
        return buf.toString();
    }

    static private void bigInteger2IpString( final StringBuilder buf, final BigInteger bigInteger, final int displayBytes )
    {
        final boolean isIPv4 = 4 == displayBytes;
        byte[] bytes = bigInteger.toByteArray();
        int diffLen = displayBytes - bytes.length;
        final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00;

        int integer;
        for ( int i = 0; i < displayBytes; i++ )
        {
            if ( 0 < i && ! isIPv4 && i % 2 == 0 )
                buf.append( ':' );
            else if ( 0 < i && isIPv4 )
                buf.append( '.' );
            integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]);
            if ( ! isIPv4 && 0x10 > integer )
                buf.append( '0' );
            buf.append( isIPv4 ? integer : Integer.toHexString( integer ) );
        }
    }
}
包de.c3oe.tryanderror;
导入java.math.biginger;
导入java.net.InetAddress;
导入java.net.UnknownHostException;
/**
*@author c3oe.de,根据斯科特·普兰特、约翰·库格尔曼的片段编写
*/
公共类子网
{
最终私有整数bytesSubnetCount;
最终私有BigInteger-bigMask;
最终私有BigInteger bigSubnetMasked;
/**通过“192.168.0.0/24”或“2001:db8:85a3:880:0:0:0/57”格式使用*/
公共子网(最终InetAddress子网地址,最终整数位)
{
this.bytesSubnetCount=subnetAddress.getAddress().length;//4或16
this.bigMask=biginger.valueOf(-1).shiftLeft(this.bytesSubnetCount*8位);//mask=-1 stringArr.length)
返回新的子网(InetAddress.getByName(stringArr[0]),(InetAddress)null);
else if(stringArr[1]。包含(“.”| | stringArr[1]。包含(“:”)
返回新的子网(InetAddress.getByName(stringArr[0]),InetAddress.getByName(stringArr[1]);
其他的
返回新的子网(InetAddress.getByName(stringArr[0]),Integer.parseInt(stringArr[1]);
}
公共布尔isInNet(最终InetAddress地址)
{
最后一个字节[]bytesAddress=address.getAddress();
if(this.bytesSubnetCount!=bytesAddress.length)
返回false;
final BigInteger bigAddress=新的BigInteger(bytesAddress);
返回bigAddress.and(this.bigsmask).equals(this.bigSubnetMasked);
}
@凌驾
最终公共布尔等于(对象obj)
{
如果(!(子网的obj实例))
返回false;
最终子网其他=(子网)obj;
返回此.bigSubnetMasked.equals(other.bigSubnetMasked)&&
this.bigMask.equals(other.bigMask)&&
this.bytesSubnetCount==other.bytesSubnetCount;
}
@凌驾
最终公共int hashCode()
{
返回此.bytesSubnetCount;
}
@凌驾
公共字符串toString()
{
最终StringBuilder buf=新StringBuilder();
bigInteger2IpString(buf,this.bigSubnetMasked,this.bytesSubnetCount);
buf.追加('/');
bigInteger2IpString(buf,this.bigMask,this.bytesSubnetCount);
返回buf.toString();
}
静态私有void bigInteger2IpString(最终StringBuilder buf、最终BigInteger、最终int displayBytes)
{
最终布尔值isIPv4=4==displayBytes;
byte[]bytes=biginger.toByteArray();
int diffLen=displayBytes-bytes.length;
最终字节fillByte=0>(int)字节[0]?(字节)0xFF:(字节)0x00;
整数;
对于(int i=0;i整数)
buf.append('0');
追加(isIPv4?整数:integer.toHexString(整数));
}
}
}

这只是带有的几行代码。免责声明:我是IPAddress库的项目经理

String subnetStr = "10.1.1.1/24";
String addrStr = "10.1.1.1";
IPAddress subnetAddress = new IPAddressString(subnetStr).getAddress();
IPAddress subnet = subnetAddress.toPrefixBlock();
IPAddress testAddress = new IPAddressString(addrStr).getAddress();
boolean result = subnet.contains(testAddress);
System.out.println(subnetAddress + " is in subnet " + subnet + " and " +
            (result ? "contains" : "does not contain") + " address " + testAddress);
输出:

10.1.1.1/24 is in subnet 10.1.1.0/24 and contains address 10.1.1.1
我相信有一个图书馆做得很好。请注意,截至2019年5月,图书馆已有2年没有更新了(可能是它已经非常成熟了)。可在

它支持使用IPv4和IPv6地址。他们的简要文档中有一些示例,说明如何检查地址是否在和的特定范围内

IPv4范围检查示例:

        String input1 = "10.1.1.1";
        Ipv4 ipv41 = Ipv4.parse(input1);

        // Using CIDR notation to specify the networkID and netmask
        Ipv4Range range = Ipv4Range.parse("10.1.1.1/32");
        boolean result = range.contains(ipv41);
        System.out.println(result); //true

        String input2 = "10.1.1.1";
        Ipv4 ipv42 = Ipv4.parse(input2);

        // Specifying the range with a start and end.
        Ipv4 start = Ipv4.of("10.1.1.1");
        Ipv4 end = Ipv4.of("10.1.1.1");
        range = Ipv4Range.from(start).to(end);

        result = range.contains(ipv42); //true
        System.out.println(result);

假设以
String ip=“10.1.1.1”开头的字符串可能重复;int mask=24
如何获取
0x0A010100
?因此在基类库或一些推荐的第三方网络掩码处理包中确实不支持此功能?重写IPv6地址的解决方案也很有用我将其与安卓一起使用以获取屏蔽的网络地址。但结果是错误的,而不是192.168.178.0我得到了0.178.168.192。你必须把24,16,8,0的顺序改为0,8,16,24。我想可能是这样
10.1.1.1/24 is in subnet 10.1.1.0/24 and contains address 10.1.1.1
        String input1 = "10.1.1.1";
        Ipv4 ipv41 = Ipv4.parse(input1);

        // Using CIDR notation to specify the networkID and netmask
        Ipv4Range range = Ipv4Range.parse("10.1.1.1/32");
        boolean result = range.contains(ipv41);
        System.out.println(result); //true

        String input2 = "10.1.1.1";
        Ipv4 ipv42 = Ipv4.parse(input2);

        // Specifying the range with a start and end.
        Ipv4 start = Ipv4.of("10.1.1.1");
        Ipv4 end = Ipv4.of("10.1.1.1");
        range = Ipv4Range.from(start).to(end);

        result = range.contains(ipv42); //true
        System.out.println(result);