簡體   English   中英

IP地址范圍的間隔分區

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM