[英]Interval Partitioning on IP address range
我正在處理對特定IP地址范圍進行分區的問題(在Java中)。 假設我有:
startIP endIP
1.2.3.4 1.2.5.6
我需要將此范圍切成每個[0,255]間隔,所以我們有:
startIP endIP
1.2.3.4 1.2.3.255
1.2.4.0 1.2.4.255
1.2.5.0 1.2.5.6
我正在或多或少地在看這個問題,例如將小數范圍from 7 to 26
,我們有[7, 9], [10, 19], [20, 26]
。 唯一的區別是我們正在處理256-simal
數的數字。 大家有什么想法嗎? 謝謝!
您可以為此使用InetAddress
,並運行一個簡單的循環來執行增量:
InetAddress from = InetAddress.getByName("1.2.3.4");
InetAddress to = InetAddress.getByName("1.2.5.6");
byte[] partsTo = to.getAddress();
for (;;) {
System.out.print(from+" - ");
byte[] parts = from.getAddress();
boolean sameUpperPart = true;
for (int i = 0 ; sameUpperPart && i < parts.length-1 ; i++) {
sameUpperPart &= (partsTo[i] == parts[i]);
}
if (sameUpperPart) {
System.out.println(to);
break;
}
int last = parts.length-1;
parts[last] = (byte)0xFF;
System.out.println(InetAddress.getByAddress(parts));
parts[last] = 0x00;
for (int i = last-1 ; i >= 0 ; i--) {
if (++parts[i] != 0) {
break;
}
}
from = InetAddress.getByAddress(parts);
}
此代碼在ideone上產生以下輸出 :
/1.2.3.4 - /1.2.3.255
/1.2.4.0 - /1.2.4.255
/1.2.5.0 - /1.2.5.6
我不知道Java的具體解決方案,但是C中有一種算法。它將IP范圍划分到最大的子網中並打印出來。 結果范圍將在子網邊界上對齊。
#define NETWORK_ZEROS(ip, prefix) ((ip) & (0xffffffff << (32 - (prefix))))
#define NETWORK_ONES(ip, prefix) ((ip) | (~ (0xffffffff << (32 - (prefix)))))
void print_ip(unsigned long ip)
{
unsigned char bytes[4];
bytes[0] = ip & 0xFF;
bytes[1] = (ip >> 8) & 0xFF;
bytes[2] = (ip >> 16) & 0xFF;
bytes[3] = (ip >> 24) & 0xFF;
printf("%d.%d.%d.%d", bytes[3], bytes[2], bytes[1], bytes[0]);
}
void partition_ip(unsigned long start, unsigned long stop)
{
int i;
while (start < stop)
{
// Change the start of the loop to 24 if you
// need to align on /24 boundaries
for (i=0; i <= 32; i++)
{
if (NETWORK_ZEROS(start, i) == start &&
NETWORK_ONES(start, i) <= stop)
{
print_ip(NETWORK_ZEROS(start, i));
printf(" - ");
print_ip(NETWORK_ONES(start, i));
printf("\n");
start = NETWORK_ONES(start, i) + 1;
break;
}
}
}
}
要將IP轉換為二進制數,只需執行以下操作
a.b.c.d => ((((a*256)+b)*256)+c)*256+d
要么
ip = (a << 24) | (b << 16) | (c << 8) | d
如果您希望通過利用位移來提高效率。
首先將IP地址轉換為一個整數,然后通過重復加256進行分區,然后再轉換回IP地址。
public class IPPartition {
public static void main(String[] args) {
String startIP = "1.2.3.4";
String endIP = "1.2.5.6";
long start = toLong(startIP);
long end = toLong(endIP);
long last = start;
long part = (start / 256 + 1) * 256;
for (; part < end; last = part, part += 256) {
System.out.println(toIP(last) + " " + toIP(part));
}
System.out.println(toIP(last) + " " + toIP(end));
}
private static long toLong(String ip) {
String[] tokens = ip.split("\\.");
long sum = 0;
for (int i = 0; i < 4; i++) {
sum *= 256;
sum += Integer.parseInt(tokens[i]);
}
return sum;
}
private static String toIP(long num) {
String result = "";
for (int i = 0; i < 4; i++) {
long section = num % 256;
result = section + result;
if (i < 3) result = "." + result;
num /= 256;
}
return result;
}
}
為了安全起見,我在這里使用了longs,但是您可能可以使用整數,但我沒有嘗試過。 可能還存在一些一次性錯誤或某些錯誤,我尚未對其進行全面測試。
一些示例代碼(假定到int []的初始轉換是在外部完成的),並且實際上並沒有返回有用的數據(只是打印)。 但是想法就在那里。
public class Convertor {
public static void convert(int []a, int []b) {
int left = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
int right = left | 0xff;
int end = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
while ( right < end ) {
System.out.printf("%s -> %s\n", toIp(left), toIp(right));
left = right + 1; right += 256;
}
System.out.printf("%s -> %s\n", toIp(left), toIp(end));
}
private static String toIp(int value) {
return String.format("%d.%d.%d.%d",
value >> 24 & 0xFF,
value >> 16 & 0xFF,
value >> 8 & 0xFF,
value & 0xFF);
}
}
致電網站:
Convertor.convert(new int[]{1, 2, 3, 4}, new int[]{1, 2, 5, 6});
輸出:
1.2.3.4 -> 1.2.3.255
1.2.4.0 -> 1.2.4.255
1.2.5.0 -> 1.2.5.6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.