在配置nginx的ip白名单时候,会通过ip段进行配置(如 10.10.10.10/24),就在思考这种配置怎么通过代码解析并判断,故通过搜索网络内容,并通过java编写测试代码。代码及说明来源网络,并进行了部分调整。故有疑问请提出来,本人小白一枚,勿喷
代码内容:获取本机ip、判断ip范围、ip与long互转等
IP: 网络地址
掩码: 指明一个IP地址的哪些位标识的是主机所在的子网。
网段:网络中可通信的部分,一般用子网第一个地址表示。
广播地址:专门用于同时向网络中所有工作站进行发送的一个地址;一般用子网最后一个地址表示。
可用子网ip:一般指子网中去除网段、广播地址的地址范围
参考
处理ip,java判断ip是否在指定的ip段范围内,给定的ip地址是否在某个ip段范围内,将字符串形式IP地址转换long类型
ip地址与掩码、网段、广播地址、可用ip范围
java实现 IP/掩码位 转换 ip段范围
192.168.和10.0.开头的IP、内网IP段、IP简介、分类——IP观止
JDK8 Java 中遇到null 和为空的情况,使用Optional来解决
什么是ip地址
代码
demo
代码参考自 参考内,并进行了部分重构
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Optional;
/**
* Ip工具类
*
* @author z.y.l
* @version v1.0
* @date 2022/12/13
*/
public class IpUtil {
private static final int I_32 = 32;
/** ip 255.255.255.255 >>> 11111111111111111111111111111111 */
private static final long VALIDATE_DATA = 4294967295L;
private static final HashMap<Integer,String> NET_MASK = new HashMap<>();
/** 1-255 正则 */
private static final String REG_1_255 = "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])";
/** 0-255 正则 */
private static final String REG_0_255 = "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)";
/** ip 正则 */
private static final String IP_REGEX = "^" + REG_1_255 + "\\." + REG_0_255 + "\\." + REG_0_255 + "\\." + REG_0_255 + "$";
static {
/* 初始化掩码 */
NET_MASK.put( I_32, long2ip( VALIDATE_DATA ) );
for(int i = 1 ; i < I_32 ; i++ ){
NET_MASK.put( I_32-i, long2ip( VALIDATE_DATA << i & VALIDATE_DATA ) );
}
}
public static void main(String[] args) {
String localIp = inetIp();
System.out.println("本机ip:"+localIp);
System.out.println("-------------");
System.out.println(new IpInf("192.168.1.2", "255.255.254.0").toString());
System.out.println(new IpInf("192.168.1.3", "255.255.255.0").toString());
System.out.println("-------------");
String ip="10.10.10.116";
String startIP = "10.10.1.0";
String endIP = "10.10.255.255";
System.out.println("ip:10.10.10.116>>>"+ip2Long(ip));
System.out.println("ip:10.10.10.116,startIP:10.10.1.0,endIP:10.10.255.255,>>>"+ipExistsIn(ip,startIP,endIP));
System.out.println("-------------");
//判断一个IP是否属于某个网段
System.out.println("ip:10.2.1.0,cip:10.2.0.0/17,>>>"+ipIsIn("10.2.1.0", "10.2.0.0/17"));
}
/**
* 获取 本机ip
* @return 本机ip
*/
public static String inetIp(){
try {
Enumeration<NetworkInterface> nif = NetworkInterface.getNetworkInterfaces();
while (nif.hasMoreElements()) {
NetworkInterface ni = nif.nextElement();
Enumeration<InetAddress> inet = ni.getInetAddresses();
while (inet.hasMoreElements()) {
InetAddress ia = inet.nextElement();
if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
return ia.getHostAddress();
}
}
}
} catch (Exception e) {
return null;
}
return "";
}
/** 判断一个ip地址是否在某个ip段范围内 */
public static boolean ipExistsIn(String ip,String start,String end){
long ipL = ip2Long(ip);
return ( ip2Long(start) <= ipL ) && ( ip2Long(end) >= ipL );
}
/**
* 功能:判断一个IP是不是在一个网段下的
* 格式:isInRange("192.168.8.3", "192.168.9.10/22");
*/
public static boolean ipIsIn(String ip,String cip){
long ipL = ip2Long(ip);
String[] split = cip.split("/");
int mask = 0xFFFFFFFF << ( 32L - s2l(split[1]));
long cipL = ip2Long(split[0]);
return ( ipL & mask ) == ( cipL & mask );
}
/** 把long类型的Ip转为一般Ip类型:xx.xx.xx.xx */
public static String long2ip(Long ip){
Long tmp = Optional.ofNullable(ip).filter(l -> l >= 0 && l <= VALIDATE_DATA )
.orElseThrow(()-> new RuntimeException(ip + " 数字 不在 有效ip范围."));
// 255.0.0.0 ~ 1.0.0.0,0.255.0.0 ~ 0.1.0.0,0.0.255.0 ~ 0.0.1.0,0.0.0.255 ~ 0.0.0.1
return (tmp>>>24) + "." + (tmp>>>16&255L) + "." + (tmp>>>8&255L) + "." + (tmp&255L);
}
/** 将字符串形式IP地址转换long类型 */
public static long ip2Long(String ip){
ip = checkIp(ip);
String[] split = ip.trim().split("\\.");
return ( s2l(split[0]) << 24 ) + ( s2l(split[1]) << 16 ) + ( s2l(split[2]) << 8 )+ ( s2l(split[3]) );
}
private static long s2l(String s){
return Long.parseLong(s,10);
}
private static String checkIp(String ip){
return Optional.ofNullable(ip).filter(s -> !s.isEmpty()&&s.matches(IP_REGEX))
.orElseThrow(() -> new RuntimeException(ip + " ip地址不合法."));
}
private static String checkMask(String mask){
return Optional.ofNullable(mask).filter(s -> !s.isEmpty()&&NET_MASK.containsValue(mask))
.orElseThrow(() -> new RuntimeException( mask + "掩码不合法."));
}
public static class IpInf{
/** ip */
private final Inf ip;
/** 掩码 */
private final Inf mask;
/** 网段 */
private final Inf segment;
/** 广播地址 */
private final Inf broadcast;
/** 开始ip */
private final Inf startIp;
/** 结束ip */
private final Inf endIp;
/** 可用ip数 */
private final Long count;
/**
* 初始化
* @param ip 如 192.168.1.1
* @param mask 掩码 如 255.255.255.255
*/
public IpInf(String ip,String mask){
System.out.println("ip:"+ip+",mask:"+mask);
this.ip = new Inf(checkIp(ip));
this.mask = new Inf(checkMask(mask));
//网段 = ip & 掩码
this.segment = new Inf(this.ip.val & this.mask.val);
// 广播地址 网段末尾用1补齐
this.broadcast = new Inf(this.segment.val | (~this.mask.val & VALIDATE_DATA));
// 开始地址 网段+1
this.startIp = new Inf(this.segment.val + 1L);
// 结束地址 广播地址-1
this.endIp = new Inf(this.broadcast.val - 1L);
this.count = this.endIp.val - this.startIp.val;
}
public Inf ip() { return ip; }
public Inf mask() { return mask; }
public Inf segment() { return segment; }
public Inf broadcast() { return broadcast; }
public Inf startIp() { return startIp; }
public Inf endIp() { return endIp; }
public Long count() { return count; }
@Override
public String toString() {
return "{ip=" + ip + ", mask=" + mask + ", segment=" + segment + ", broadcast=" + broadcast
+ ", startIp=" + startIp + ", endIp=" + endIp + ", count=" + count + '}';
}
}
public static class Inf{
private final String lab;
private final Long val;
Inf(String l){ this.lab = l;this.val = ip2Long(l); }
Inf(Long v){ this.val = v;this.lab = long2ip(v); }
public Long toLong() { return val; }
public String toStr() { return lab; }
@Override
public String toString() {
return "{str='" + lab + "', long=" + val + '}';
}
}
}
测试
本机ip:192.168.***.171
-------------
ip:192.168.1.2,mask:255.255.254.0
{ip={str='192.168.1.2', long=3232235778}, mask={str='255.255.254.0', long=4294966784}, segment={str='192.168.0.0', long=3232235520}, broadcast={str='192.168.1.255', long=3232236031}, startIp={str='192.168.0.1', long=3232235521}, endIp={str='192.168.1.254', long=3232236030}, count=509}
ip:192.168.1.3,mask:255.255.255.0
{ip={str='192.168.1.3', long=3232235779}, mask={str='255.255.255.0', long=4294967040}, segment={str='192.168.1.0', long=3232235776}, broadcast={str='192.168.1.255', long=3232236031}, startIp={str='192.168.1.1', long=3232235777}, endIp={str='192.168.1.254', long=3232236030}, count=253}
-------------
ip:10.10.10.116>>>168430196
ip:10.10.10.116,startIP:10.10.1.0,endIP:10.10.255.255,>>>true
-------------
ip:10.2.1.0,cip:10.2.0.0/17,>>>true
截图
END
代码仅供参考,请充分测试后在使用。谢谢Thanks♪(・ω・)ノ