Java 验证 IP 地址(带掩码)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4209760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validate an IP Address (with Mask)
提问by Josh K
I have ip addresses and a mask such as 10.1.1.1/32
. I would like to check if 10.1.1.1
is inside that range. Is there a library or utility that would do this or do I need to write something myself?
我有 IP 地址和掩码,例如10.1.1.1/32
. 我想检查是否10.1.1.1
在该范围内。是否有一个库或实用程序可以做到这一点,或者我需要自己编写一些东西吗?
采纳答案by John Kugelman
First you'll want to convert your IP addresses into flat int
s, which will be easier to work with:
首先,您需要将您的 IP 地址转换为 flat int
s,这将更容易使用:
String s = "10.1.1.99";
Inet4Address a = (Inet4Address) InetAddress.getByName(s);
byte[] b = a.getAddress();
int i = ((b[0] & 0xFF) << 24) |
((b[1] & 0xFF) << 16) |
((b[2] & 0xFF) << 8) |
((b[3] & 0xFF) << 0);
Once you have your IP addresses as plain int
s you can do some bit arithmetic to perform the check:
将 IP 地址设为普通int
s 后,您可以进行一些算术运算来执行检查:
int subnet = 0x0A010100; // 10.1.1.0/24
int bits = 24;
int ip = 0x0A010199; // 10.1.1.99
// Create bitmask to clear out irrelevant bits. For 10.1.1.0/24 this is
// 0xFFFFFF00 -- the first 24 bits are 1's, the last 8 are 0's.
//
// -1 == 0xFFFFFFFF
// 32 - bits == 8
// -1 << 8 == 0xFFFFFF00
mask = -1 << (32 - bits)
if ((subnet & mask) == (ip & mask)) {
// IP address is in the subnet.
}
回答by Scott Plante
Thanks to John Kugelman--I used his code snippets to create this class.
感谢 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;
}
}
I did have to add a mask to the int conversion in his code:
我确实必须在他的代码中为 int 转换添加一个掩码:
Inet4Address a = (Inet4Address) InetAddress.getByName("192.192.192.192");
byte[] b = a.getAddress();
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0);
System.out.println(Integer.toHexString(i));
System.out.println(Integer.toHexString(addrToInt(a)));
Produced:
出品:
ffffffc0
c0c0c0c0
On my system:
在我的系统上:
$> 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)
$>
You can remove the main and test methods from the above class. They're adapted from the unit test code and added here for simplicity.
您可以从上述类中删除 main 和 test 方法。它们改编自单元测试代码,为简单起见添加到此处。
回答by Sri Ram
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;
}
}
回答by Carsten
Here is a version that takes subnet descriptions in several common ways, including IPv6.
这是一个以多种常见方式获取子网描述的版本,包括IPv6。
Based on the other code posted here.
On IPv4addresses it might work slower than the approach of performing binary operations on bare int
's.
基于此处发布的其他代码。在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 ) );
}
}
}
回答by Sean F
This is just a few lines of code with the open-source IPAddress Java library. Disclaimer: I am the project manager of the IPAddress library.
这只是带有开源 IPAddress Java 库的几行代码。免责声明:我是 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);
Output:
输出:
10.1.1.1/24 is in subnet 10.1.1.0/24 and contains address 10.1.1.1
回答by railomaya
There is commons-ip-mathlibrary that I believe does a very good job. Please note that as of May 2019, there hasn't been any updates to the library for 2 years (Could be that its already very mature library). Its available on maven-central
我相信有一个commons-ip-math库做得很好。请注意,截至 2019 年 5 月,该库已有 2 年没有任何更新(可能是它已经非常成熟的库)。它在maven-central上可用
It supports working with both IPv4 and IPv6 addresses. Their brief documentation has examples on how you can check if an address is in a specific range for IPv4and IPv6
它支持使用 IPv4 和 IPv6 地址。他们的简短文档包含有关如何检查地址是否在IPv4和IPv6的特定范围内的示例
Example for IPv4 range checking:
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);