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

我在看这个问题或多或少像划分一个十进制范围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 转换为二进制数,只需执行以下操作

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

一些示例代码(假设初始转换为 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 回答
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,但您也许可以使用整数,我还没有尝试过。也可能有一些错误或其他东西,我没有彻底测试过。

于 2012-08-23T22:19:32.080 回答