IPv4地址範圍與網絡地址/子網掩碼的轉換,點分十進制與數字掩碼的轉換

private static final int IPV4BYTES = 4; // IPv4字節數爲4
private static final int BYTEBITS = 8; // 每個字節的比特位長度爲8

/* IPv4,計算一個地址範圍所屬最小"網絡地址/子網掩碼"
    例:1.1.0.1-1.1.3.10或者1.1.3.10-1.1.0.1
    1.1.0.1: 00000001 00000001 00000001 00000001
    1.1.3.10:00000001 00000001 00000011 00001010
    從左至右找到第一個不同所在位置,得到子網掩碼爲22
    將子網掩碼後面的位數置爲0,得到網絡地址1.1.0.0
    返回1.1.0.0/22
  */
public static String getNetworkAddressAndNumMask(String startAddress, String endAddress) {
    String networkAddress = "";
    int mask = 0;

    // 用.分隔起始地址和結束地址,並將String型數組轉爲int型數組
    String[] startStrArr = startAddress.split("\\.");
    int[] startNums = Arrays.asList(startStrArr).stream().mapToInt(Integer::parseInt).toArray();
    String[] endStrArr = endAddress.split("\\.");
    int[] endNums = Arrays.asList(endStrArr).stream().mapToInt(Integer::parseInt).toArray();

    // 計算子網掩碼
    for (int i = 0; i < IPV4BYTES; i++) {
        int xorValue = startNums[i] ^ endNums[i]; // 異或操作
        if (xorValue > 0) {
            for (int j = 1; j <= BYTEBITS; j++) {
                if ((xorValue >>> j) == 0) { // 右移直至爲0
                    mask += (BYTEBITS - j); // 8減右移位數爲網絡位
                    break;
                }
            }
        } else { // 如果異或值爲0,則目前的8位爲網絡位
            mask += BYTEBITS;
        }
    }

    // 計算網絡地址
    int[] networkNums = new int[IPV4BYTES];
    for (int i = 0; i < IPV4BYTES; i++) {
        if (mask / BYTEBITS > i) {
            networkNums[i] = startNums[i];
        } else if (mask / BYTEBITS == i) {
            networkNums[i] = startNums[i] & (255 << (BYTEBITS - mask % BYTEBITS));
        } else {
            networkNums[i] = 0;
        }
    }
    networkAddress = StringUtils.join(networkNums, ".");

    return networkAddress + "/" + mask;
}

/* IPv4,計算一個地址範圍所屬最小"網絡地址 點分十進制掩碼"
    例:1.1.0.1-1.1.3.10返回1.1.0.0 255.255.252.0
  */
public static String getNetworkAddressAndDottedDecimalMask(String startAddress, String endAddress) {
    String networkMask = getNetworkAddressAndNumMask(startAddress, endAddress);
    String networkAddress = networkMask.split("/")[0]; // 網絡地址
    int numMask = Integer.parseInt(networkMask.split("/")[1]); // 子網掩碼,數字

    String dottedDecimalMask = numMaskToDottedDecimalMask(numMask); // 子網掩碼,點分十進制

    return networkAddress + " " + dottedDecimalMask;
}

// IPv4,將子網掩碼數字轉爲點分十進制
public static String numMaskToDottedDecimalMask(int numMask) {
    int[] networkNums = new int[IPV4BYTES];

    for (int i = 0; i < IPV4BYTES; i++) {
        if (numMask / BYTEBITS > i) {
            networkNums[i] = 255;
        } else if (numMask / BYTEBITS == i) {
            networkNums[i] = (255 << (BYTEBITS - numMask % BYTEBITS)) & 255;
        } else {
            networkNums[i] = 0;
        }
    }

    return StringUtils.join(networkNums, ".");
}

// IPv4,將子網掩碼點分十進制轉爲數字
public static int dottedDecimalMaskToNumMask(String dottedDecimalMask) {
    int numMask = 0;

    String[] maskStr = dottedDecimalMask.split("\\.");
    int[] maskInt = Arrays.asList(maskStr).stream().mapToInt(Integer::parseInt).toArray();

    for (int i = 0; i < IPV4BYTES && maskInt[i] > 0; i++) {
        for (int j = 1; j <= BYTEBITS; j++) {
            if ((maskInt[i] << j & 255) == 0) { // 左移,直至遇到0
                numMask += j;
            }
        }
    }

    return numMask;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章