You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调试Groovy CIDR子网可用IP生成代码:返回空列表问题

调试CIDR子网可用IP生成代码

你的代码返回空列表的核心问题在于子网掩码的计算逻辑错误,以及后续广播地址计算时的有符号整数溢出问题,导致循环条件不成立,没有生成任何IP。

问题分析

  • 子网掩码整数计算错误
    原代码中subnetMaskInt = (1 << (32 - subnetMask.toInteger())) - 1的逻辑完全颠倒:这个计算得到的是主机位全1的数值,而非子网掩码(子网掩码要求网络位全1、主机位全0)。比如对于/27,32-27=5,计算结果是31(二进制00011111),但正确的子网掩码应该是0xFFFFFFE0(二进制11111111 11111111 11111111 11100000)。

  • 广播地址计算的有符号整数问题
    由于子网掩码计算错误,~subnetMaskInt在Groovy的有符号整数环境下会生成负数,导致broadcastAddress为负数,lastUsableIp = broadcastAddress -1也变成负数,而firstUsableIp是正数,循环条件i <= lastUsableIp永远不成立,因此没有IP被添加到列表中。

修正后的代码

static List<String> generateAvailableIps(String subnetCidr) {
    // Parse the CIDR notation
    def (ipAddress, subnetMaskStr) = subnetCidr.split("/")
    int mask = subnetMaskStr.toInteger()

    // Convert IP address to 32-bit integer
    def ipInt = ipAddress.split("\\.").inject(0) { acc, value -> (acc << 8) + value.toInteger() }

    // Calculate correct subnet mask (network bits set to 1)
    def subnetMaskInt = (-1) << (32 - mask)
    // Ensure we're dealing with unsigned 32-bit value
    subnetMaskInt &= 0xFFFFFFFF

    // Get network address
    def networkAddress = ipInt & subnetMaskInt

    // Calculate host bits range for broadcast address
    def hostBits = (1 << (32 - mask)) - 1
    def broadcastAddress = networkAddress | hostBits

    // Determine usable IP range (exclude network and broadcast)
    def firstUsableIp = networkAddress + 1
    def lastUsableIp = broadcastAddress - 1

    def availableIps = []
    // Handle edge cases like /31 (no usable IPs) or /32 (single IP, no usable)
    if (firstUsableIp <= lastUsableIp) {
        for (long i = firstUsableIp; i <= lastUsableIp; i++) {
            def octet1 = (i >> 24) & 0xff
            def octet2 = (i >> 16) & 0xff
            def octet3 = (i >> 8) & 0xff
            def octet4 = i & 0xff
            availableIps.add("$octet1.$octet2.$octet3.$octet4")
        }
    }

    return availableIps
}

// Example usage
def availableIps = generateAvailableIps("192.168.35.32/27")
println(availableIps)

关键修改说明

  • 修正子网掩码计算:使用(-1) << (32 - mask)生成网络位全1的子网掩码,再通过& 0xFFFFFFFF确保数值为无符号32位整数,避免负数问题。
  • 广播地址计算优化:直接通过networkAddress | hostBits生成广播地址(hostBits是主机位全1的数值),逻辑更清晰且避免有符号整数问题。
  • 添加边界判断:当firstUsableIp > lastUsableIp时(比如/31、/32子网),跳过循环,避免无效执行。
  • 循环变量改为long:防止IP整数超过int的范围(IPv4最大数值为2^32-1,刚好触及int的边界,用long更安全)。

运行修正后的代码,192.168.35.32/27子网会返回正确的可用IP列表:[192.168.35.33, 192.168.35.34, ..., 192.168.35.62](共30个可用IP)。

内容的提问来源于stack exchange,提问作者Prashant Shete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:00:32