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

如何使用Dart计算CIDR格式IP段的起始与结束IP地址

CIDR格式IPv4转起止IP区间(Dart实现)

核心计算逻辑

  • 拆分输入:将CIDR字符串按/分割,得到点分十进制IP段和前缀长度n,n的合法取值范围为0~32,超出范围直接判定为非法输入。
  • IP转32位整数:把点分四段的IPv4每段转成0~255的整数,从左到右按第一段 << 24 | 第二段 << 16 | 第三段 << 8 | 第四段的规则,拼成一个32位整数,方便做位运算。
  • 计算子网掩码:前缀长度n代表前n位是网络位,掩码值为(0xFFFFFFFF << (32 - n)) & 0xFFFFFFFF,末尾做与运算避免Dart整数移位时出现符号位异常。
  • 计算网络地址:将IP对应的32位整数和子网掩码做按位与运算,得到当前IP所在子网的网络地址(主机位全0)。
  • 计算主机位掩码:主机位长度为32-n,主机位全1的掩码值为(1 << (32 - n)) - 1。
  • 计算广播地址:网络地址和主机位掩码做按位或运算,得到子网的广播地址(主机位全1)。
  • 取可用IP区间:常规场景下网络地址(主机位全0)和广播地址(主机位全1)不分配给主机使用,因此实际起止IP为网络地址 + 1到广播地址 - 1;前缀长度为32时,32-n=0,网络地址和广播地址都是输入IP本身,区间就是单个IP。

注:你问题描述中198.162.1.1/24对应的结束IP写为124是笔误,按照计算逻辑/24前缀的可用IP区间是198.162.1.1 - 198.162.1.254,和你给出的192.168.0.1/25输出192.168.0.1 - 192.168.0.126的逻辑完全匹配。

Dart实现代码

/// 将CIDR格式IPv4地址转换为 起始IP - 结束IP 格式的字符串
/// 输入示例:192.168.0.1/25
/// 输出示例:192.168.0.1 - 192.168.0.126
String cidrToIpRange(String cidr) {
  // 拆分CIDR字符串
  final parts = cidr.split('/');
  if (parts.length != 2) {
    throw ArgumentError('非法CIDR格式,正确格式示例:192.168.0.1/25');
  }
  final ipStr = parts[0];
  final prefixLength = int.tryParse(parts[1]);
  if (prefixLength == null || prefixLength < 0 || prefixLength > 32) {
    throw ArgumentError('前缀长度非法,IPv4前缀长度需在0~32之间');
  }

  // 拆分IP段并转换为32位整数
  final ipParts = ipStr.split('.');
  if (ipParts.length != 4) {
    throw ArgumentError('IP格式非法,需为点分十进制四段格式');
  }
  int ipInt = 0;
  for (int i = 0; i < 4; i++) {
    final segment = int.tryParse(ipParts[i]);
    if (segment == null || segment < 0 || segment > 255) {
      throw ArgumentError('IP段值非法,每段需在0~255之间');
    }
    ipInt = (ipInt << 8) | segment;
  }

  // 计算掩码、网络地址、广播地址
  final mask = prefixLength == 0 ? 0 : (0xFFFFFFFF << (32 - prefixLength)) & 0xFFFFFFFF;
  final networkAddr = ipInt & mask;
  final hostMask = prefixLength == 32 ? 0 : (1 << (32 - prefixLength)) - 1;
  final broadcastAddr = networkAddr | hostMask;

  // 计算起止IP,处理特殊前缀场景
  int startIpInt;
  int endIpInt;
  if (prefixLength == 32) {
    // 32位前缀为单主机地址
    startIpInt = ipInt;
    endIpInt = ipInt;
  } else if (prefixLength == 31) {
    // 31位前缀为点对点链路专用,两个地址均可使用
    startIpInt = networkAddr;
    endIpInt = broadcastAddr;
  } else {
    // 常规场景排除网络地址、广播地址
    startIpInt = networkAddr + 1;
    endIpInt = broadcastAddr - 1;
  }

  // 32位整数转回点分十进制IP
  String intToIp(int ipNum) {
    return [
      (ipNum >> 24) & 0xFF,
      (ipNum >> 16) & 0xFF,
      (ipNum >> 8) & 0xFF,
      ipNum & 0xFF
    ].join('.');
  }

  return '${intToIp(startIpInt)} - ${intToIp(endIpInt)}';
}

// 测试用例
void main() {
  print(cidrToIpRange('192.168.0.1/25')); // 输出:192.168.0.1 - 192.168.0.126
  print(cidrToIpRange('198.162.1.1/24')); // 输出:198.162.1.1 - 198.162.1.254
  print(cidrToIpRange('10.0.0.5/32')); // 输出:10.0.0.5 - 10.0.0.5
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:06:27