如何从 IP 范围中获取单独的连续 IP 块?
How can i get individual sequential IP blocks from an IP Range?
给定一个 ip 范围,例如 41.216.124.0-41.216.127.27,我想得到以下内容:
41.216.124.*
41.216.125.*
41.216.126.*
41.216.127.*
同样给定 128.1.0.1-191.255.255.254 我想单独列出它们
128.1.0.1-255
128.1.1-255.*
128.2-255.*
.*
129-190.*
.*
191.0-254.*
.*
191.255.*
191.255.255.*
我尝试了各种方法,包括使用正则表达式来匹配不重复的字段并尝试找出差异。我遇到了一个非常好的库 https://seancfoley.github.io/IPAddress/ by https://whosebug.com/users/6801443/sean-f 我尝试了以下方法,但似乎无法在文档中找到实现它的方法。
var ipRange1 = "128.1.0.1-191.255.255.254"; //ipRange1 example
var ipRange2 = "41.216.124.0-41.216.127.27"; //ipRange2 example
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressString;
String[] subString = ipRange2.split("-");
IPAddressString startIP = new IPAddressString(subString[0]);
IPAddressString endIP = new IPAddressString(subString[1]);
IPAddress one = startIP.getAddress(), two = endIP.getAddress();
IPAddressSeqRange range = one.toSequentialRange(two);
var ips = new HashSet<String>();
IPAddress blocks[] = range.spanWithSequentialBlocks(); // 41.216.124-126.```*```
即使没有这个库,在 Java 中是否仍然可以做到这一点?我试图查询的 API 使用 IP 前缀,这就是为什么我要解决所有问题。
这是我的初步尝试。您必须意识到您所说的范围非常大。我正在使用长整数来避免 LongStream
范围内的有符号整数问题。
public static void main(String[] args) {
printIPs("192.148.233.0", "192.148.245.3", 32);
}
public static void printIPs(String start, String end, int mask) {
LongStream.rangeClosed(toLong(start, mask), toLong(end, mask))
.mapToObj(ip-> toIP(ip, mask))
.forEach(System.out::println);
}
public static String toIP(long lv, int mask) {
lv <<= (32-mask);
String ip = String.join(".",
Long.toString((lv >> 24) & 0xFF),
Long.toString((lv >> 16) & 0xFF),
Long.toString((lv >> 8) & 0xFF),
Long.toString(lv & 0xFF));
return ip;
}
public static long toLong(String ip, int mask) {
String[] n = ip.split("\.");
long v = Integer.valueOf(n[0]);
v <<= 8;
v |= Integer.valueOf(n[1]);
v <<= 8;
v |= Integer.valueOf(n[2]);
v <<= 8;
v |= Integer.valueOf(n[3]);
return v >> (32-mask);
}
}
}
给定一个 ip 范围,例如 41.216.124.0-41.216.127.27,我想得到以下内容:
41.216.124.*
41.216.125.*
41.216.126.*
41.216.127.*
同样给定 128.1.0.1-191.255.255.254 我想单独列出它们 128.1.0.1-255
128.1.1-255.*
128.2-255.*
.*
129-190.*
.*
191.0-254.*
.*
191.255.*
191.255.255.*
我尝试了各种方法,包括使用正则表达式来匹配不重复的字段并尝试找出差异。我遇到了一个非常好的库 https://seancfoley.github.io/IPAddress/ by https://whosebug.com/users/6801443/sean-f 我尝试了以下方法,但似乎无法在文档中找到实现它的方法。
var ipRange1 = "128.1.0.1-191.255.255.254"; //ipRange1 example
var ipRange2 = "41.216.124.0-41.216.127.27"; //ipRange2 example
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressString;
String[] subString = ipRange2.split("-");
IPAddressString startIP = new IPAddressString(subString[0]);
IPAddressString endIP = new IPAddressString(subString[1]);
IPAddress one = startIP.getAddress(), two = endIP.getAddress();
IPAddressSeqRange range = one.toSequentialRange(two);
var ips = new HashSet<String>();
IPAddress blocks[] = range.spanWithSequentialBlocks(); // 41.216.124-126.```*```
即使没有这个库,在 Java 中是否仍然可以做到这一点?我试图查询的 API 使用 IP 前缀,这就是为什么我要解决所有问题。
这是我的初步尝试。您必须意识到您所说的范围非常大。我正在使用长整数来避免 LongStream
范围内的有符号整数问题。
public static void main(String[] args) {
printIPs("192.148.233.0", "192.148.245.3", 32);
}
public static void printIPs(String start, String end, int mask) {
LongStream.rangeClosed(toLong(start, mask), toLong(end, mask))
.mapToObj(ip-> toIP(ip, mask))
.forEach(System.out::println);
}
public static String toIP(long lv, int mask) {
lv <<= (32-mask);
String ip = String.join(".",
Long.toString((lv >> 24) & 0xFF),
Long.toString((lv >> 16) & 0xFF),
Long.toString((lv >> 8) & 0xFF),
Long.toString(lv & 0xFF));
return ip;
}
public static long toLong(String ip, int mask) {
String[] n = ip.split("\.");
long v = Integer.valueOf(n[0]);
v <<= 8;
v |= Integer.valueOf(n[1]);
v <<= 8;
v |= Integer.valueOf(n[2]);
v <<= 8;
v |= Integer.valueOf(n[3]);
return v >> (32-mask);
}
}
}