2

特定の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

この問題は、たとえば10進数の範囲を分割するようなもので、多かれ少なかれ見てfrom 7 to 26[7, 9], [10, 19], [20, 26]ます。256-simal唯一の違いは、数値を扱っていることです。何かアイデアはありますか?ありがとうございました!

4

4 に答える 4

2

これに使用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
于 2012-08-23T22:22:06.830 に答える
1

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を2進数に変換するには、次のようにします。

a.b.c.d => ((((a*256)+b)*256)+c)*256+d

また

ip = (a << 24) | (b << 16) | (c << 8) | d

ビットシフトを利用してより効率的にしたい場合。

于 2012-08-23T22:16:23.940 に答える
1

最初に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;
    }
}

ここでは安全のためにlongを使用しましたが、整数を使用できる可能性があるため、試していません。また、1つずつエラーが発生する可能性もありますが、十分にテストしていません。

于 2012-08-23T22:19:32.080 に答える
1

一部のサンプルコード(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
于 2012-08-23T22:34:54.263 に答える