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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章