编辑代码

/**
 * 将IP地址字符串转换为32位整数
 * @param {string} ip - IPv4地址(如 "192.168.1.1")
 * @returns {number} 32位整数形式的IP地址
 */
function ipToInt(ip) {
    return ip.split('.').reduce((acc, octet, index) => {
        return acc + (parseInt(octet, 10) << (24 - index * 8));
    }, 0);
}

/**
 * 将子网掩码转换为CIDR前缀长度
 * @param {string} mask - 子网掩码(如 "255.255.255.0")
 * @returns {number} 前缀长度(如 24)
 */
function maskToPrefix(mask) {
    const maskInt = ipToInt(mask);
    let prefix = 0;
    for (let i = 31; i >= 0; i--) {
        if ((maskInt & (1 << i)) !== 0) prefix++;
        else break;
    }
    return prefix;
}

/**
 * 将32位整数转换为IP地址字符串
 * @param {number} int - 32位整数形式的IP地址
 * @returns {string} IPv4地址(如 "192.168.1.1")
 */
function intToIp(int) {
    return [
        (int >>> 24) & 0xff,
        (int >>> 16) & 0xff,
        (int >>> 8) & 0xff,
        int & 0xff
    ].join('.');
}

/**
 * 计算IP地址池范围
 * @param {string} ip - IPv4地址
 * @param {string} mask - 子网掩码
 * @returns {Object} 包含起始地址和结束地址的对象
 */
function calculateIPRange(ip, mask) {
    const ipInt = ipToInt(ip);
    const maskInt = ipToInt(mask);
    const prefix = maskToPrefix(mask);
    const hostBits = 32 - prefix;
    const networkInt = ipInt & maskInt;

    let startInt, endInt;

    if (hostBits === 0) { // /32 掩码特殊情况
        startInt = networkInt;
        endInt = networkInt;
    } else {
        startInt = networkInt + 1;
        const broadcastInt = networkInt | ((1 << hostBits) - 1);
        endInt = broadcastInt - 1;
    }

    return {
        start: intToIp(startInt),
        end: intToIp(endInt)
    };
}

// ----------------- 示例用法 -------------------
// 示例1:常规地址
const example1 = calculateIPRange('10.56.101.1', '254.0.0.0');
console.log('示例1结果:', example1); 

// 示例2:小型子网(/30)
const example2 = calculateIPRange('10.0.0.5', '255.255.255.252');
console.log('示例2结果:', example2); 
// 输出: { start: '10.0.0.5', end: '10.0.0.6' }

// 示例3:/32 掩码(单个地址)
const example3 = calculateIPRange('172.16.0.1', '255.255.255.255');
console.log('示例3结果:', example3); 
// 输出: { start: '172.16.0.1', end: '172.16.0.1' }