今天拿到个需求要搜索ip地址匹配时候需要匹配网段中的IP,靠network网段地址后面的掩码长度计算是否包含某个ip,这种事情,我们每次都是网上找个在线计算器算一下, 不过想了想这么多策略包含太多的网段,有的是这种场景需要查询某个ip是否在某个网段中,所以理了理思路写个方法
1、网段地址,可以根据掩码长度来计算出来主机范围,
我们的掩码格式:ip/mask-length 即:172.30.28.0/24,很标准的使用网段网关地址/子网掩码来表示,
2、计算给定IP的二进制地址,判断主机位是否在这个网段中
写个方法试试看:
/**
* 判断给定IP地址是否在指定网段中
* network eg:172.30.29.0/25
* ip eg: 172.30.29.129
* @param network
* @param ip
* @return
*/
public Boolean isContains(String network, String ip) {
String[] networkArr = network.split("/");
String networkBin = transIpToBrinary(networkArr[0]);
String ipBin = transIpToBrinary(ip);
int mask = Integer.parseInt(networkArr[1]);
//如果掩码长度不在1-32之间,就直接比较俩地址吧
if (mask < 0 || mask >= 32)
return ip.equals(network);
//这一步实际是想求ip地址的大段,没想好怎么算,就先这样算了
int targetMask = mask / 8;
int newMask = targetMask * 8;
//根据network地址求出网段中最大的主机地址
// (这里包含广播地址,既然是匹配IP是否在此网段中,就未对广播地址及网关地址清除)
StringBuilder networkMaxHostBuilder = new StringBuilder();
networkMaxHostBuilder.append(networkBin, 0, mask); //取网络位
for (int i = mask; i < 32; i++) {
networkMaxHostBuilder.append("1"); // 主机位补上1,这就拼成了此网段中最大主机地址
}
//截取主机位转换为十进制,进行比较
int networkMinHost = Integer.parseInt(networkBin.substring(newMask, 32), 2);
int networkMaxHost = Integer.parseInt(networkMaxHostBuilder.substring(newMask, 32), 2);
int ipBinary = Integer.parseInt(ipBin.substring(newMask, 32), 2);
//网络位要相等
if (networkBin.substring(0, newMask).equals(ipBin.substring(0, newMask))) {
//且必须在主机地址中
if (ipBinary >= networkMinHost && ipBinary <= networkMaxHost)
return true;
}
return false;
}
/**
* 转换ip地址
* @param ip
* @return
*/
private String transIpToBrinary(String ip) {
String[] ipArr = ip.split("\\.");
String net;
StringBuilder netBuilder = new StringBuilder();
int ipLen = ipArr.length;
for (int i = 0; i < ipLen; i++) {
net = doTransToBinary(ipArr[i]);
netBuilder.append(net);
}
return netBuilder.toString();
}
/**
* 转换十进制为二进制
* @param ip
* @return
*/
private String doTransToBinary(String ip) {
int numInt = Integer.parseInt(ip);
StringBuilder binaryBuilder = new StringBuilder();
for (int i = 7; i >= 0; i--) {
int binary = numInt >>> i & 1;
binaryBuilder.append(binary);
}
return binaryBuilder.toString();
}
测试了几遍,没啥问题,如果有更好的思路和实现方法,麻烦提供一下,谢谢啦,
就先这样了,写的很急,也没来的及优化,捕获异常,变量名标准之类的,各位看官如果需要,记得捕获异常优化一下然后多测几遍,我得下班了。