Java无法直接用InetAddress或NetworkInterface判断IP是否在指定网段,需手动实现IP与子网掩码的按位与运算,或使用Apache Commons Net的SubnetUtils(注意版本兼容性及IPv6支持)。

Java里用InetAddress和NetworkInterface没法直接判断网段
很多人试过把IP转成InetAddress,再调用isReachable()或查NetworkInterface,结果发现这俩根本不做子网匹配——它们只管连通性或本机接口列表,和“192.168.1.5是否在192.168.1.0/24里”完全无关。
真正要做的,是手动做**IP地址与子网掩码的按位与运算**,比对网络地址是否一致。Java没内置这个逻辑,得自己写或借助轻量工具类。
-
getByName()只能解析字符串为IP,不带网段语义 -
NetworkInterface.getNetworkInterfaces()返回的是本机已配置的网段,不是用来校验任意IP的 - 别依赖
URL或URI类,它们根本不处理掩码
手写判断逻辑:把IP和掩码都转成int再与运算
IPv4地址本质是32位无符号整数,子网判断就是看两个IP做&后是否等于网络地址。关键在正确解析点分十进制、处理掩码(如/24或255.255.255.0)。
示例片段:
立即学习“Java免费学习笔记(深入)”;
public static boolean isInSubnet(String ip, String cidr) {
int ipInt = ipToInt(ip);
int[] netAndMask = cidrToNetmask(cidr); // 返回 {networkAddr, mask}
return (ipInt & netAndMask[1]) == netAndMask[0];
}
- 注意
ipToInt("0.0.0.0")必须返回0,高位补零不能丢 -
cidrToNetmask("10.0.0.0/8")要能识别/8并生成255.0.0.0对应的整数 - 遇到
"255.255.255.255"这种掩码,&后只剩IP本身,等效于精确匹配
用Apache Commons Net的SubnetUtils省事但要注意版本
如果项目已引入commons-net,SubnetUtils是最省心的选择,但它在3.9.0+才支持IPv6,且老版本(如3.3)对/32或0.0.0.0/0处理有边界bug。
- 初始化时传
"192.168.1.0/24",别传"192.168.1.100/24"——网络地址必须是合法的网段起始地址 -
utils.getInfo().isInRange("192.168.1.255")才有效;用错构造参数会抛IllegalArgumentException - 它内部也是转int+位运算,只是帮你封装了掩码解析和异常校验
IPv6场景下BigInteger是绕不开的
IPv6地址128位,超出了long范围,必须用BigInteger。别试图用String.split(":")手动拼——压缩格式(如::1)会让解析崩溃。
- 用
InetAddress.getByName()解析IPv6字符串最稳,再调getAddress()拿字节数组 - 把16字节转
BigInteger时注意符号位:new BigInteger(1, bytes),否则负数会出错 -
SubnetUtils在3.9.0之前根本不支持IPv6,硬上得自己实现&逻辑
/)、以及把广播地址当网络地址传入,这四类问题占了八成以上报错。写完务必用"127.0.0.1/32"和"0.0.0.0/0"这种边界值测一遍。










