测试ip地址是否在由具有网络掩码的ip地址定义的地址空间内。
/* * Copyright (c) 2011-2012 ICM Uniwersytet Warszawski All rights reserved. * See LICENCE file for licensing information. * * Derived from the code copyrighted and licensed as follows: * * Copyright (c) Members of the EGEE Collaboration. 2004. * See http://www.eu-egee.org/partners/ for details on the copyright * holders. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //package com.nowjava; /** from 时代Java公众号 - nowjava.com**/ public class Main { public static void main(String[] argv) throws Exception { byte[] ipBytes = new byte[] { 34, 35, 36, 37, 37, 37, 67, 68, 69 }; byte[] ipAddressWithNetmask = new byte[] { 34, 35, 36, 37, 37, 37, 67, 68, 69 }; System.out.println(isWithinAddressSpace(ipBytes, ipAddressWithNetmask)); } private static final int IPv4_FULL_MASK = 32; private static final int IPv6_FULL_MASK = 128; private static final int IPv6_HALF_MASK = 64; /** * Tests whether the ipAddress is within the address space defined by * the ipAddressWithNetmask. * * @param ipBytes * The IP address bytes to compare against the address * space. * @param ipAddressWithNetmask * The 8 (IPv4) or 32 (IPv6) byte array containing in the * first half the base IP address bytes and in the second * half the netmask bytes. * @return true if ip matches subnet. */ public static boolean isWithinAddressSpace(byte[] ipBytes, byte[] ipAddressWithNetmask) { if (!(ipAddressWithNetmask.length == 8 && ipBytes.length == 4)/**时代Java公众号**/ && !(ipAddressWithNetmask.length == 32 && ipBytes.length == 16)) { throw new IllegalArgumentException( "IP address and IP address-netmask length mismatch, should be either (4 and 8) or (16 and 32), actual lengths were: " + ipBytes.length + " and " + ipAddressWithNetmask.length + "."); } if (ipBytes.length == 4) { int mask = getCidrNetmask(4, ipAddressWithNetmask, 4); /* * IPv4 can be represented as a 32 bit ints. */ int ipAsInt = getInt(ipBytes, 0); int netAsInt = getInt(ipAddressWithNetmask, 0); return (ipAsInt ^ netAsInt) >> (IPv4_FULL_MASK - mask) == 0; } /** * IPv6 can be represented as two 64 bit longs. * * We evaluate second long only if bitmask bigger than 64. The * second longs are created only if needed as it turned to be * the slowest part. */ long ipAsLong0 = getLong(ipBytes, 0); long netAsLong0 = getLong(ipAddressWithNetmask, 0); int mask = getCidrNetmask(16, ipAddressWithNetmask, 16); if (mask > 64) { long ipAsLong1 = getLong(ipBytes, 8); long netAsLong1 = getLong(ipAddressWithNetmask, 8); return (ipAsLong0 == netAsLong0) & (ipAsLong1 ^ netAsLong1) >> (IPv6_FULL_MASK - mask) == 0; } return (ipAsLong0 ^ netAsLong0) >> (IPv6_HALF_MASK - mask) == 0; } private static int getCidrNetmask(int size, byte[] netmask, int offset) { int ret = 0; for (int i = 0; i < size; i++) { if (netmask[i + offset] != -1) //-1 == 255 unsigned { int maskByteReversed = (~(netmask[i + offset])) & 0xff; int bitPfx = Integer.numberOfLeadingZeros(maskByteReversed) - 24; return ret + bitPfx; } else ret += 8; } return ret; } /** * Returns the big-endian {@code int} value whose byte representation is * the 4 bytes of <code>bytes</code> staring <code>offset</code>. * * @param bytes * @param offset * @return int value */ private static int getInt(byte[] bytes, int offset) { return (bytes[offset + 0] &