VLSM子网划分
格式: 子网名称 + 主机数量,点击添加按钮添加到列表
暂无子网需求
子网合并
超网计算
到
网络规划
计算结果
使用说明
VLSM子网划分
- 输入网络地址和子网掩码(CIDR格式)
- 添加各个子网的主机需求
- 系统自动计算最优的子网划分方案
- 支持按主机数量优化排序
子网合并
- 输入多个子网地址(每行一个)
- 选择合并策略和选项
- 系统计算最优的合并方案
- 支持相邻和连续子网合并
超网计算
- 输入IP地址范围(起始IP到结束IP)
- 选择超网类型和计算选项
- 系统计算包含该范围的最小超网
- 支持自定义掩码位数
网络规划
- 输入可用的地址空间
- 添加各部门的主机需求
- 选择规划策略和选项
- 生成完整的网络规划方案
示例代码
各语言示例代码
-
SubnetCalculator (JAVA)
1import java.util.*; 2import java.util.regex.Pattern; 3import java.util.regex.Matcher; 4 5/** 6 * 子网划分工具 - Java版本 7 * 支持VLSM可变长子网掩码、子网合并、超网计算、网络规划等功能 8 */ 9public class SubnetCalculator { 10 private static final Pattern IP_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); 11 private static final Pattern CIDR_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/([0-9]|[1-2][0-9]|3[0-2])$"); 12 13 // 子网需求类 14 public static class SubnetRequirement { 15 private String name; 16 private int hosts; 17 18 public SubnetRequirement(String name, int hosts) { 19 this.name = name; 20 this.hosts = hosts; 21 } 22 23 public String getName() { return name; } 24 public int getHosts() { return hosts; } 25 } 26 27 // 部门需求类 28 public static class DepartmentRequirement { 29 private String name; 30 private int size; 31 32 public DepartmentRequirement(String name, int size) { 33 this.name = name; 34 this.size = size; 35 } 36 37 public String getName() { return name; } 38 public int getSize() { return size; } 39 } 40 41 // VLSM结果类 42 public static class VLSMResult { 43 private List<SubnetInfo> subnets; 44 private SummaryInfo summary; 45 private String details; 46 47 public VLSMResult(List<SubnetInfo> subnets, SummaryInfo summary, String details) { 48 this.subnets = subnets; 49 this.summary = summary; 50 this.details = details; 51 } 52 53 public List<SubnetInfo> getSubnets() { return subnets; } 54 public SummaryInfo getSummary() { return summary; } 55 public String getDetails() { return details; } 56 } 57 58 // 子网信息类 59 public static class SubnetInfo { 60 private String name; 61 private String networkAddress; 62 private String subnetMask; 63 private int cidr; 64 private String firstHost; 65 private String lastHost; 66 private String broadcastAddress; 67 private int usableHosts; 68 private int requiredHosts; 69 70 public SubnetInfo(String name, String networkAddress, String subnetMask, int cidr, 71 String firstHost, String lastHost, String broadcastAddress, 72 int usableHosts, int requiredHosts) { 73 this.name = name; 74 this.networkAddress = networkAddress; 75 this.subnetMask = subnetMask; 76 this.cidr = cidr; 77 this.firstHost = firstHost; 78 this.lastHost = lastHost; 79 this.broadcastAddress = broadcastAddress; 80 this.usableHosts = usableHosts; 81 this.requiredHosts = requiredHosts; 82 } 83 84 // Getters 85 public String getName() { return name; } 86 public String getNetworkAddress() { return networkAddress; } 87 public String getSubnetMask() { return subnetMask; } 88 public int getCidr() { return cidr; } 89 public String getFirstHost() { return firstHost; } 90 public String getLastHost() { return lastHost; } 91 public String getBroadcastAddress() { return broadcastAddress; } 92 public int getUsableHosts() { return usableHosts; } 93 public int getRequiredHosts() { return requiredHosts; } 94 } 95 96 // 汇总信息类 97 public static class SummaryInfo { 98 private String originalNetwork; 99 private int totalSubnets; 100 private int totalHosts; 101 private double utilization; 102 103 public SummaryInfo(String originalNetwork, int totalSubnets, int totalHosts, double utilization) { 104 this.originalNetwork = originalNetwork; 105 this.totalSubnets = totalSubnets; 106 this.totalHosts = totalHosts; 107 this.utilization = utilization; 108 } 109 110 // Getters 111 public String getOriginalNetwork() { return originalNetwork; } 112 public int getTotalSubnets() { return totalSubnets; } 113 public int getTotalHosts() { return totalHosts; } 114 public double getUtilization() { return utilization; } 115 } 116 117 // 合并结果类 118 public static class MergeResult { 119 private List<MergedSubnet> mergedSubnets; 120 private MergeSummary summary; 121 private String details; 122 123 public MergeResult(List<MergedSubnet> mergedSubnets, MergeSummary summary, String details) { 124 this.mergedSubnets = mergedSubnets; 125 this.summary = summary; 126 this.details = details; 127 } 128 129 public List<MergedSubnet> getMergedSubnets() { return mergedSubnets; } 130 public MergeSummary getSummary() { return summary; } 131 public String getDetails() { return details; } 132 } 133 134 // 合并后的子网类 135 public static class MergedSubnet { 136 private String network; 137 private List<String> originalSubnets; 138 private int hostCount; 139 140 public MergedSubnet(String network, List<String> originalSubnets, int hostCount) { 141 this.network = network; 142 this.originalSubnets = originalSubnets; 143 this.hostCount = hostCount; 144 } 145 146 // Getters 147 public String getNetwork() { return network; } 148 public List<String> getOriginalSubnets() { return originalSubnets; } 149 public int getHostCount() { return hostCount; } 150 } 151 152 // 合并汇总信息类 153 public static class MergeSummary { 154 private int originalCount; 155 private int mergedCount; 156 private int reduction; 157 private int totalHosts; 158 private double utilization; 159 160 public MergeSummary(int originalCount, int mergedCount, int reduction, int totalHosts, double utilization) { 161 this.originalCount = originalCount; 162 this.mergedCount = mergedCount; 163 this.reduction = reduction; 164 this.totalHosts = totalHosts; 165 this.utilization = utilization; 166 } 167 168 // Getters 169 public int getOriginalCount() { return originalCount; } 170 public int getMergedCount() { return mergedCount; } 171 public int getReduction() { return reduction; } 172 public int getTotalHosts() { return totalHosts; } 173 public double getUtilization() { return utilization; } 174 } 175 176 // 超网结果类 177 public static class SupernetResult { 178 private String networkAddress; 179 private String subnetMask; 180 private int cidr; 181 private String broadcastAddress; 182 private String firstHost; 183 private String lastHost; 184 private int totalHosts; 185 private String startIP; 186 private String endIP; 187 private String details; 188 189 public SupernetResult(String networkAddress, String subnetMask, int cidr, 190 String broadcastAddress, String firstHost, String lastHost, 191 int totalHosts, String startIP, String endIP, String details) { 192 this.networkAddress = networkAddress; 193 this.subnetMask = subnetMask; 194 this.cidr = cidr; 195 this.broadcastAddress = broadcastAddress; 196 this.firstHost = firstHost; 197 this.lastHost = lastHost; 198 this.totalHosts = totalHosts; 199 this.startIP = startIP; 200 this.endIP = endIP; 201 this.details = details; 202 } 203 204 // Getters 205 public String getNetworkAddress() { return networkAddress; } 206 public String getSubnetMask() { return subnetMask; } 207 public int getCidr() { return cidr; } 208 public String getBroadcastAddress() { return broadcastAddress; } 209 public String getFirstHost() { return firstHost; } 210 public String getLastHost() { return lastHost; } 211 public int getTotalHosts() { return totalHosts; } 212 public String getStartIP() { return startIP; } 213 public String getEndIP() { return endIP; } 214 public String getDetails() { return details; } 215 } 216 217 // 规划结果类 218 public static class PlanningResult { 219 private List<DepartmentInfo> departments; 220 private PlanningSummary summary; 221 private String details; 222 223 public PlanningResult(List<DepartmentInfo> departments, PlanningSummary summary, String details) { 224 this.departments = departments; 225 this.summary = summary; 226 this.details = details; 227 } 228 229 public List<DepartmentInfo> getDepartments() { return departments; } 230 public PlanningSummary getSummary() { return summary; } 231 public String getDetails() { return details; } 232 } 233 234 // 部门信息类 235 public static class DepartmentInfo { 236 private String name; 237 private String networkAddress; 238 private String subnetMask; 239 private int cidr; 240 private String firstHost; 241 private String lastHost; 242 private int allocatedHosts; 243 private int totalHosts; 244 245 public DepartmentInfo(String name, String networkAddress, String subnetMask, int cidr, 246 String firstHost, String lastHost, int allocatedHosts, int totalHosts) { 247 this.name = name; 248 this.networkAddress = networkAddress; 249 this.subnetMask = subnetMask; 250 this.cidr = cidr; 251 this.firstHost = firstHost; 252 this.lastHost = lastHost; 253 this.allocatedHosts = allocatedHosts; 254 this.totalHosts = totalHosts; 255 } 256 257 // Getters 258 public String getName() { return name; } 259 public String getNetworkAddress() { return networkAddress; } 260 public String getSubnetMask() { return subnetMask; } 261 public int getCidr() { return cidr; } 262 public String getFirstHost() { return firstHost; } 263 public String getLastHost() { return lastHost; } 264 public int getAllocatedHosts() { return allocatedHosts; } 265 public int getTotalHosts() { return totalHosts; } 266 } 267 268 // 规划汇总信息类 269 public static class PlanningSummary { 270 private int totalSpace; 271 private int allocatedSpace; 272 private int remainingSpace; 273 private double utilization; 274 private int departmentCount; 275 276 public PlanningSummary(int totalSpace, int allocatedSpace, int remainingSpace, 277 double utilization, int departmentCount) { 278 this.totalSpace = totalSpace; 279 this.allocatedSpace = allocatedSpace; 280 this.remainingSpace = remainingSpace; 281 this.utilization = utilization; 282 this.departmentCount = departmentCount; 283 } 284 285 // Getters 286 public int getTotalSpace() { return totalSpace; } 287 public int getAllocatedSpace() { return allocatedSpace; } 288 public int getRemainingSpace() { return remainingSpace; } 289 public double getUtilization() { return utilization; } 290 public int getDepartmentCount() { return departmentCount; } 291 } 292 293 /** 294 * 验证IP地址格式 295 */ 296 public boolean validateIP(String ip) { 297 return IP_PATTERN.matcher(ip).matches(); 298 } 299 300 /** 301 * 验证CIDR格式 302 */ 303 public boolean validateCIDR(String cidr) { 304 return CIDR_PATTERN.matcher(cidr).matches(); 305 } 306 307 /** 308 * IP地址转换为长整数 309 */ 310 public long ipToLong(String ip) throws IllegalArgumentException { 311 if (!validateIP(ip)) { 312 throw new IllegalArgumentException("无效的IP地址格式"); 313 } 314 315 String[] parts = ip.split("\\."); 316 long result = 0; 317 for (int i = 0; i < 4; i++) { 318 result = result << 8 | Integer.parseInt(parts[i]); 319 } 320 return result; 321 } 322 323 /** 324 * 长整数转换为IP地址 325 */ 326 public String longToIP(long ipLong) { 327 return String.format("%d.%d.%d.%d", 328 (ipLong >> 24) & 0xFF, 329 (ipLong >> 16) & 0xFF, 330 (ipLong >> 8) & 0xFF, 331 ipLong & 0xFF); 332 } 333 334 /** 335 * 获取子网掩码 336 */ 337 public String getSubnetMask(int cidr) { 338 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 339 return longToIP(mask); 340 } 341 342 /** 343 * 获取网络地址 344 */ 345 public String getNetworkAddress(String ip, int cidr) throws IllegalArgumentException { 346 long ipLong = ipToLong(ip); 347 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 348 long networkLong = ipLong & mask; 349 return longToIP(networkLong); 350 } 351 352 /** 353 * 获取广播地址 354 */ 355 public String getBroadcastAddress(String ip, int cidr) throws IllegalArgumentException { 356 long ipLong = ipToLong(ip); 357 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 358 long broadcastLong = ipLong | (~mask & 0xFFFFFFFFL); 359 return longToIP(broadcastLong); 360 } 361 362 /** 363 * 获取第一个可用主机地址 364 */ 365 public String getFirstHost(String ip, int cidr) throws IllegalArgumentException { 366 String networkIP = getNetworkAddress(ip, cidr); 367 long networkLong = ipToLong(networkIP); 368 return longToIP(networkLong + 1); 369 } 370 371 /** 372 * 获取最后一个可用主机地址 373 */ 374 public String getLastHost(String ip, int cidr) throws IllegalArgumentException { 375 String broadcastIP = getBroadcastAddress(ip, cidr); 376 long broadcastLong = ipToLong(broadcastIP); 377 return longToIP(broadcastLong - 1); 378 } 379 380 /** 381 * 计算可用主机数量 382 */ 383 public int getUsableHosts(int cidr) { 384 return (int) (Math.pow(2, 32 - cidr) - 2); 385 } 386 387 /** 388 * 解析CIDR格式 389 */ 390 public String[] parseCIDR(String cidr) throws IllegalArgumentException { 391 if (!validateCIDR(cidr)) { 392 throw new IllegalArgumentException("无效的CIDR格式"); 393 } 394 395 String[] parts = cidr.split("/"); 396 return new String[]{parts[0], parts[1]}; 397 } 398 399 /** 400 * VLSM子网划分 401 */ 402 public VLSMResult calculateVLSM(String networkCIDR, List<SubnetRequirement> subnetRequirements, 403 Map<String, Object> options) throws IllegalArgumentException { 404 String[] parsed = parseCIDR(networkCIDR); 405 String networkIP = parsed[0]; 406 int networkCIDRBits = Integer.parseInt(parsed[1]); 407 408 String networkAddress = getNetworkAddress(networkIP, networkCIDRBits); 409 long networkLong = ipToLong(networkAddress); 410 int totalHosts = getUsableHosts(networkCIDRBits); 411 412 // 按主机数量排序(如果需要) 413 List<SubnetRequirement> sortedRequirements = new ArrayList<>(subnetRequirements); 414 if (options != null && options.containsKey("optimize_order") && 415 (Boolean) options.get("optimize_order")) { 416 sortedRequirements.sort((a, b) -> Integer.compare(b.getHosts(), a.getHosts())); 417 } 418 419 // 计算每个子网需要的掩码位数 420 List<SubnetInfo> subnets = new ArrayList<>(); 421 long currentNetworkLong = networkLong; 422 423 for (SubnetRequirement requirement : sortedRequirements) { 424 int requiredHosts = requirement.getHosts(); 425 if (options != null && options.containsKey("include_network_broadcast") && 426 (Boolean) options.get("include_network_broadcast")) { 427 requiredHosts += 2; 428 } 429 430 int requiredCIDR = 32 - (int) Math.ceil(Math.log(requiredHosts) / Math.log(2)); 431 432 if (requiredCIDR < networkCIDRBits) { 433 throw new IllegalArgumentException("子网 " + requirement.getName() + " 需要的主机数超出可用空间"); 434 } 435 436 String subnetNetworkIP = longToIP(currentNetworkLong); 437 String subnetMask = getSubnetMask(requiredCIDR); 438 int subnetHosts = getUsableHosts(requiredCIDR); 439 440 String firstHost = getFirstHost(subnetNetworkIP, requiredCIDR); 441 String lastHost = getLastHost(subnetNetworkIP, requiredCIDR); 442 String broadcastAddress = getBroadcastAddress(subnetNetworkIP, requiredCIDR); 443 444 subnets.add(new SubnetInfo( 445 requirement.getName(), 446 subnetNetworkIP, 447 subnetMask, 448 requiredCIDR, 449 firstHost, 450 lastHost, 451 broadcastAddress, 452 subnetHosts, 453 requirement.getHosts() 454 )); 455 456 // 计算下一个子网的起始地址 457 long subnetSize = (long) Math.pow(2, 32 - requiredCIDR); 458 currentNetworkLong += subnetSize; 459 } 460 461 // 计算汇总信息 462 int totalRequiredHosts = sortedRequirements.stream().mapToInt(SubnetRequirement::getHosts).sum(); 463 double utilization = (double) totalRequiredHosts / totalHosts * 100; 464 465 return new VLSMResult( 466 subnets, 467 new SummaryInfo(networkCIDR, subnets.size(), totalRequiredHosts, utilization), 468 String.format("VLSM划分完成,共创建 %d 个子网,地址利用率 %.2f%%", subnets.size(), utilization) 469 ); 470 } 471 472 /** 473 * 子网合并 474 */ 475 public MergeResult mergeSubnets(List<String> subnetList, Map<String, Object> options) 476 throws IllegalArgumentException { 477 List<SubnetData> subnets = new ArrayList<>(); 478 479 // 解析子网列表 480 for (String subnetStr : subnetList) { 481 if (!validateCIDR(subnetStr)) { 482 if (options != null && options.containsKey("validate_subnets") && 483 (Boolean) options.get("validate_subnets")) { 484 throw new IllegalArgumentException("无效的子网格式: " + subnetStr); 485 } 486 continue; 487 } 488 489 String[] parsed = parseCIDR(subnetStr); 490 String ip = parsed[0]; 491 int cidr = Integer.parseInt(parsed[1]); 492 493 String networkIP = getNetworkAddress(ip, cidr); 494 long networkLong = ipToLong(networkIP); 495 496 subnets.add(new SubnetData(subnetStr, networkIP, cidr, networkLong, getUsableHosts(cidr))); 497 } 498 499 if (subnets.isEmpty()) { 500 throw new IllegalArgumentException("没有有效的子网可以合并"); 501 } 502 503 // 按网络地址排序 504 subnets.sort(Comparator.comparingLong(SubnetData::getNetworkLong)); 505 506 List<MergedSubnet> mergedSubnets = new ArrayList<>(); 507 List<SubnetData> currentGroup = new ArrayList<>(); 508 currentGroup.add(subnets.get(0)); 509 510 for (int i = 1; i < subnets.size(); i++) { 511 SubnetData current = subnets.get(i); 512 SubnetData last = currentGroup.get(currentGroup.size() - 1); 513 514 // 检查是否相邻或连续 515 boolean isAdjacent = false; 516 boolean isContiguous = false; 517 518 if (options != null && options.containsKey("merge_adjacent") && 519 (Boolean) options.get("merge_adjacent")) { 520 isAdjacent = areSubnetsAdjacent(last, current); 521 } 522 523 if (options != null && options.containsKey("merge_contiguous") && 524 (Boolean) options.get("merge_contiguous")) { 525 isContiguous = areSubnetsContiguous(last, current); 526 } 527 528 if (isAdjacent || isContiguous) { 529 currentGroup.add(current); 530 } else { 531 // 合并当前组 532 if (currentGroup.size() > 1) { 533 mergedSubnets.add(mergeSubnetGroup(currentGroup)); 534 } else { 535 List<String> originalSubnets = new ArrayList<>(); 536 originalSubnets.add(currentGroup.get(0).getNetwork()); 537 mergedSubnets.add(new MergedSubnet( 538 currentGroup.get(0).getNetwork(), 539 originalSubnets, 540 currentGroup.get(0).getHostCount() 541 )); 542 } 543 currentGroup = new ArrayList<>(); 544 currentGroup.add(current); 545 } 546 } 547 548 // 处理最后一组 549 if (currentGroup.size() > 1) { 550 mergedSubnets.add(mergeSubnetGroup(currentGroup)); 551 } else { 552 List<String> originalSubnets = new ArrayList<>(); 553 originalSubnets.add(currentGroup.get(0).getNetwork()); 554 mergedSubnets.add(new MergedSubnet( 555 currentGroup.get(0).getNetwork(), 556 originalSubnets, 557 currentGroup.get(0).getHostCount() 558 )); 559 } 560 561 // 计算汇总信息 562 int originalCount = subnets.size(); 563 int mergedCount = mergedSubnets.size(); 564 int reduction = originalCount - mergedCount; 565 int totalHosts = mergedSubnets.stream().mapToInt(MergedSubnet::getHostCount).sum(); 566 567 return new MergeResult( 568 mergedSubnets, 569 new MergeSummary(originalCount, mergedCount, reduction, totalHosts, 570 (double) totalHosts / 0xFFFFFFFFL * 100), 571 String.format("合并完成,从 %d 个子网合并为 %d 个,减少 %d 个", originalCount, mergedCount, reduction) 572 ); 573 } 574 575 // 子网数据内部类 576 private static class SubnetData { 577 private String network; 578 private String networkIP; 579 private int cidr; 580 private long networkLong; 581 private int hostCount; 582 583 public SubnetData(String network, String networkIP, int cidr, long networkLong, int hostCount) { 584 this.network = network; 585 this.networkIP = networkIP; 586 this.cidr = cidr; 587 this.networkLong = networkLong; 588 this.hostCount = hostCount; 589 } 590 591 public String getNetwork() { return network; } 592 public String getNetworkIP() { return networkIP; } 593 public int getCidr() { return cidr; } 594 public long getNetworkLong() { return networkLong; } 595 public int getHostCount() { return hostCount; } 596 } 597 598 /** 599 * 检查两个子网是否相邻 600 */ 601 private boolean areSubnetsAdjacent(SubnetData subnet1, SubnetData subnet2) { 602 String broadcast1 = getBroadcastAddress(subnet1.getNetworkIP(), subnet1.getCidr()); 603 long broadcast1Long = ipToLong(broadcast1); 604 return subnet2.getNetworkLong() == broadcast1Long + 1; 605 } 606 607 /** 608 * 检查两个子网是否连续 609 */ 610 private boolean areSubnetsContiguous(SubnetData subnet1, SubnetData subnet2) { 611 String broadcast1 = getBroadcastAddress(subnet1.getNetworkIP(), subnet1.getCidr()); 612 long broadcast1Long = ipToLong(broadcast1); 613 return subnet2.getNetworkLong() <= broadcast1Long + 1; 614 } 615 616 /** 617 * 合并子网组 618 */ 619 private MergedSubnet mergeSubnetGroup(List<SubnetData> subnetGroup) { 620 SubnetData first = subnetGroup.get(0); 621 SubnetData last = subnetGroup.get(subnetGroup.size() - 1); 622 String lastBroadcast = getBroadcastAddress(last.getNetworkIP(), last.getCidr()); 623 long lastBroadcastLong = ipToLong(lastBroadcast); 624 625 // 计算合并后的CIDR 626 long rangeSize = lastBroadcastLong - first.getNetworkLong() + 1; 627 int mergedCIDR = 32 - (int) Math.ceil(Math.log(rangeSize) / Math.log(2)); 628 629 String mergedNetworkIP = longToIP(first.getNetworkLong()); 630 String mergedNetwork = mergedNetworkIP + "/" + mergedCIDR; 631 int mergedHostCount = getUsableHosts(mergedCIDR); 632 633 List<String> originalSubnets = new ArrayList<>(); 634 for (SubnetData subnet : subnetGroup) { 635 originalSubnets.add(subnet.getNetwork()); 636 } 637 638 return new MergedSubnet(mergedNetwork, originalSubnets, mergedHostCount); 639 } 640 641 /** 642 * 超网计算 643 */ 644 public SupernetResult calculateSupernet(String startIP, String endIP, Map<String, Object> options) 645 throws IllegalArgumentException { 646 if (!validateIP(startIP) || !validateIP(endIP)) { 647 throw new IllegalArgumentException("无效的IP地址格式"); 648 } 649 650 long startLong = ipToLong(startIP); 651 long endLong = ipToLong(endIP); 652 653 if (startLong > endLong) { 654 throw new IllegalArgumentException("起始IP不能大于结束IP"); 655 } 656 657 // 计算包含该范围的最小超网 658 long rangeSize = endLong - startLong + 1; 659 int requiredCIDR = 32 - (int) Math.ceil(Math.log(rangeSize) / Math.log(2)); 660 661 // 找到包含该范围的最小网络地址 662 long mask = (0xFFFFFFFFL << (32 - requiredCIDR)) & 0xFFFFFFFFL; 663 long networkLong = startLong & mask; 664 String networkIP = longToIP(networkLong); 665 666 // 验证该网络是否包含整个范围 667 long broadcastLong = networkLong | (~mask & 0xFFFFFFFFL); 668 if (broadcastLong < endLong) { 669 // 需要更大的网络 670 int newCIDR = requiredCIDR - 1; 671 long newMask = (0xFFFFFFFFL << (32 - newCIDR)) & 0xFFFFFFFFL; 672 long newNetworkLong = startLong & newMask; 673 String newNetworkIP = longToIP(newNetworkLong); 674 675 return new SupernetResult( 676 newNetworkIP, 677 getSubnetMask(newCIDR), 678 newCIDR, 679 longToIP(newNetworkLong | (~newMask & 0xFFFFFFFFL)), 680 longToIP(newNetworkLong + 1), 681 longToIP((newNetworkLong | (~newMask & 0xFFFFFFFFL)) - 1), 682 getUsableHosts(newCIDR), 683 startIP, 684 endIP, 685 String.format("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, newNetworkIP, newCIDR) 686 ); 687 } 688 689 return new SupernetResult( 690 networkIP, 691 getSubnetMask(requiredCIDR), 692 requiredCIDR, 693 longToIP(broadcastLong), 694 longToIP(networkLong + 1), 695 longToIP(broadcastLong - 1), 696 getUsableHosts(requiredCIDR), 697 startIP, 698 endIP, 699 String.format("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, networkIP, requiredCIDR) 700 ); 701 } 702 703 /** 704 * 网络规划 705 */ 706 public PlanningResult generateNetworkPlan(String addressSpace, List<DepartmentRequirement> departmentRequirements, 707 Map<String, Object> options) throws IllegalArgumentException { 708 String[] parsed = parseCIDR(addressSpace); 709 String networkIP = parsed[0]; 710 int networkCIDRBits = Integer.parseInt(parsed[1]); 711 712 String networkAddress = getNetworkAddress(networkIP, networkCIDRBits); 713 long networkLong = ipToLong(networkAddress); 714 int totalSpace = getUsableHosts(networkCIDRBits); 715 716 // 按部门大小排序 717 List<DepartmentRequirement> sortedDepartments = new ArrayList<>(departmentRequirements); 718 if (options != null && options.containsKey("optimize_utilization") && 719 (Boolean) options.get("optimize_utilization")) { 720 sortedDepartments.sort((a, b) -> Integer.compare(b.getSize(), a.getSize())); 721 } 722 723 List<DepartmentInfo> departments = new ArrayList<>(); 724 long currentNetworkLong = networkLong; 725 int allocatedSpace = 0; 726 727 for (DepartmentRequirement dept : sortedDepartments) { 728 int requiredHosts = dept.getSize(); 729 if (options != null && options.containsKey("reserve_space") && 730 (Boolean) options.get("reserve_space")) { 731 requiredHosts += (int) Math.ceil(dept.getSize() * 0.2); 732 } 733 734 int requiredCIDR = 32 - (int) Math.ceil(Math.log(requiredHosts + 2) / Math.log(2)); // +2 for network and broadcast 735 736 if (requiredCIDR < networkCIDRBits) { 737 throw new IllegalArgumentException("部门 " + dept.getName() + " 需要的主机数超出可用空间"); 738 } 739 740 String deptNetworkIP = longToIP(currentNetworkLong); 741 String deptSubnetMask = getSubnetMask(requiredCIDR); 742 int deptHosts = getUsableHosts(requiredCIDR); 743 744 String firstHost = getFirstHost(deptNetworkIP, requiredCIDR); 745 String lastHost = getLastHost(deptNetworkIP, requiredCIDR); 746 747 departments.add(new DepartmentInfo( 748 dept.getName(), 749 deptNetworkIP, 750 deptSubnetMask, 751 requiredCIDR, 752 firstHost, 753 lastHost, 754 dept.getSize(), 755 deptHosts 756 )); 757 758 allocatedSpace += deptHosts; 759 long subnetSize = (long) Math.pow(2, 32 - requiredCIDR); 760 currentNetworkLong += subnetSize; 761 } 762 763 int remainingSpace = totalSpace - allocatedSpace; 764 double utilization = (double) allocatedSpace / totalSpace * 100; 765 766 return new PlanningResult( 767 departments, 768 new PlanningSummary(totalSpace, allocatedSpace, remainingSpace, utilization, departments.size()), 769 String.format("网络规划完成,共分配 %d 个部门,地址利用率 %.2f%%,剩余空间 %d 个主机", 770 departments.size(), utilization, remainingSpace) 771 ); 772 } 773 774 public static void main(String[] args) { 775 SubnetCalculator calculator = new SubnetCalculator(); 776 777 System.out.println("=== 子网划分工具 - Java版本 ==="); 778 779 // VLSM示例 780 System.out.println("\n--- VLSM子网划分示例 ---"); 781 try { 782 List<SubnetRequirement> requirements = Arrays.asList( 783 new SubnetRequirement("销售部", 50), 784 new SubnetRequirement("技术部", 30), 785 new SubnetRequirement("财务部", 10), 786 new SubnetRequirement("人事部", 5) 787 ); 788 789 Map<String, Object> options = new HashMap<>(); 790 options.put("optimize_order", true); 791 options.put("include_network_broadcast", true); 792 793 VLSMResult vlsmResult = calculator.calculateVLSM("192.168.1.0/24", requirements, options); 794 System.out.println("VLSM结果:"); 795 for (SubnetInfo subnet : vlsmResult.getSubnets()) { 796 System.out.printf(" %s: %s/%d (%s - %s)%n", 797 subnet.getName(), subnet.getNetworkAddress(), subnet.getCidr(), 798 subnet.getFirstHost(), subnet.getLastHost()); 799 } 800 System.out.printf("汇总: 原始网络=%s, 总子网数=%d, 总主机数=%d, 利用率=%.2f%%%n", 801 vlsmResult.getSummary().getOriginalNetwork(), 802 vlsmResult.getSummary().getTotalSubnets(), 803 vlsmResult.getSummary().getTotalHosts(), 804 vlsmResult.getSummary().getUtilization()); 805 } catch (Exception e) { 806 System.err.println("VLSM错误: " + e.getMessage()); 807 } 808 809 // 子网合并示例 810 System.out.println("\n--- 子网合并示例 ---"); 811 try { 812 List<String> subnetList = Arrays.asList( 813 "192.168.1.0/26", 814 "192.168.1.64/26", 815 "192.168.1.128/26", 816 "192.168.1.192/26" 817 ); 818 819 Map<String, Object> options = new HashMap<>(); 820 options.put("merge_adjacent", true); 821 options.put("merge_contiguous", true); 822 options.put("validate_subnets", true); 823 824 MergeResult mergeResult = calculator.mergeSubnets(subnetList, options); 825 System.out.println("合并结果:"); 826 for (MergedSubnet merged : mergeResult.getMergedSubnets()) { 827 System.out.printf(" %s (包含: %s)%n", merged.getNetwork(), 828 String.join(", ", merged.getOriginalSubnets())); 829 } 830 System.out.printf("汇总: 原子网数=%d, 合并后=%d, 减少=%d, 利用率=%.4f%%%n", 831 mergeResult.getSummary().getOriginalCount(), 832 mergeResult.getSummary().getMergedCount(), 833 mergeResult.getSummary().getReduction(), 834 mergeResult.getSummary().getUtilization()); 835 } catch (Exception e) { 836 System.err.println("合并错误: " + e.getMessage()); 837 } 838 839 // 超网计算示例 840 System.out.println("\n--- 超网计算示例 ---"); 841 try { 842 SupernetResult supernetResult = calculator.calculateSupernet("192.168.1.10", "192.168.1.50", null); 843 System.out.printf("超网结果: %s/%d%n", supernetResult.getNetworkAddress(), supernetResult.getCidr()); 844 System.out.printf("详细信息: %s%n", supernetResult.getDetails()); 845 } catch (Exception e) { 846 System.err.println("超网错误: " + e.getMessage()); 847 } 848 849 // 网络规划示例 850 System.out.println("\n--- 网络规划示例 ---"); 851 try { 852 List<DepartmentRequirement> deptRequirements = Arrays.asList( 853 new DepartmentRequirement("总部", 200), 854 new DepartmentRequirement("分公司A", 100), 855 new DepartmentRequirement("分公司B", 80), 856 new DepartmentRequirement("研发中心", 150) 857 ); 858 859 Map<String, Object> options = new HashMap<>(); 860 options.put("optimize_utilization", true); 861 options.put("reserve_space", true); 862 863 PlanningResult planningResult = calculator.generateNetworkPlan("10.0.0.0/8", deptRequirements, options); 864 System.out.println("规划结果:"); 865 for (DepartmentInfo dept : planningResult.getDepartments()) { 866 System.out.printf(" %s: %s/%d (%d 主机)%n", dept.getName(), 867 dept.getNetworkAddress(), dept.getCidr(), dept.getAllocatedHosts()); 868 } 869 System.out.printf("汇总: 总空间=%d, 已分配=%d, 剩余=%d, 利用率=%.2f%%, 部门数=%d%n", 870 planningResult.getSummary().getTotalSpace(), 871 planningResult.getSummary().getAllocatedSpace(), 872 planningResult.getSummary().getRemainingSpace(), 873 planningResult.getSummary().getUtilization(), 874 planningResult.getSummary().getDepartmentCount()); 875 } catch (Exception e) { 876 System.err.println("规划错误: " + e.getMessage()); 877 } 878 } 879}
-
subnet_calculator (GO)
1package main 2 3import ( 4 "fmt" 5 "math" 6 "net" 7 "regexp" 8 "sort" 9 "strconv" 10 "strings" 11) 12 13// SubnetCalculator 子网划分计算器结构体 14type SubnetCalculator struct { 15 ipRegex *regexp.Regexp 16 cidrRegex *regexp.Regexp 17} 18 19// SubnetRequirement 子网需求结构体 20type SubnetRequirement struct { 21 Name string `json:"name"` 22 Hosts int `json:"hosts"` 23} 24 25// DepartmentRequirement 部门需求结构体 26type DepartmentRequirement struct { 27 Name string `json:"name"` 28 Size int `json:"size"` 29} 30 31// VLSMResult VLSM计算结果结构体 32type VLSMResult struct { 33 Subnets []SubnetInfo `json:"subnets"` 34 Summary SummaryInfo `json:"summary"` 35 Details string `json:"details"` 36} 37 38// SubnetInfo 子网信息结构体 39type SubnetInfo struct { 40 Name string `json:"name"` 41 NetworkAddress string `json:"network_address"` 42 SubnetMask string `json:"subnet_mask"` 43 CIDR int `json:"cidr"` 44 FirstHost string `json:"first_host"` 45 LastHost string `json:"last_host"` 46 BroadcastAddress string `json:"broadcast_address"` 47 UsableHosts int `json:"usable_hosts"` 48 RequiredHosts int `json:"required_hosts"` 49} 50 51// SummaryInfo 汇总信息结构体 52type SummaryInfo struct { 53 OriginalNetwork string `json:"original_network"` 54 TotalSubnets int `json:"total_subnets"` 55 TotalHosts int `json:"total_hosts"` 56 Utilization float64 `json:"utilization"` 57} 58 59// MergeResult 子网合并结果结构体 60type MergeResult struct { 61 MergedSubnets []MergedSubnet `json:"merged_subnets"` 62 Summary MergeSummary `json:"summary"` 63 Details string `json:"details"` 64} 65 66// MergedSubnet 合并后的子网结构体 67type MergedSubnet struct { 68 Network string `json:"network"` 69 OriginalSubnets []string `json:"original_subnets"` 70 HostCount int `json:"host_count"` 71} 72 73// MergeSummary 合并汇总信息结构体 74type MergeSummary struct { 75 OriginalCount int `json:"original_count"` 76 MergedCount int `json:"merged_count"` 77 Reduction int `json:"reduction"` 78 TotalHosts int `json:"total_hosts"` 79 Utilization float64 `json:"utilization"` 80} 81 82// SupernetResult 超网计算结果结构体 83type SupernetResult struct { 84 NetworkAddress string `json:"network_address"` 85 SubnetMask string `json:"subnet_mask"` 86 CIDR int `json:"cidr"` 87 BroadcastAddress string `json:"broadcast_address"` 88 FirstHost string `json:"first_host"` 89 LastHost string `json:"last_host"` 90 TotalHosts int `json:"total_hosts"` 91 StartIP string `json:"start_ip"` 92 EndIP string `json:"end_ip"` 93 Details string `json:"details"` 94} 95 96// PlanningResult 网络规划结果结构体 97type PlanningResult struct { 98 Departments []DepartmentInfo `json:"departments"` 99 Summary PlanningSummary `json:"summary"` 100 Details string `json:"details"` 101} 102 103// DepartmentInfo 部门信息结构体 104type DepartmentInfo struct { 105 Name string `json:"name"` 106 NetworkAddress string `json:"network_address"` 107 SubnetMask string `json:"subnet_mask"` 108 CIDR int `json:"cidr"` 109 FirstHost string `json:"first_host"` 110 LastHost string `json:"last_host"` 111 AllocatedHosts int `json:"allocated_hosts"` 112 TotalHosts int `json:"total_hosts"` 113} 114 115// PlanningSummary 规划汇总信息结构体 116type PlanningSummary struct { 117 TotalSpace int `json:"total_space"` 118 AllocatedSpace int `json:"allocated_space"` 119 RemainingSpace int `json:"remaining_space"` 120 Utilization float64 `json:"utilization"` 121 DepartmentCount int `json:"department_count"` 122} 123 124// NewSubnetCalculator 创建新的子网计算器 125func NewSubnetCalculator() *SubnetCalculator { 126 return &SubnetCalculator{ 127 ipRegex: regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`), 128 cidrRegex: regexp.MustCompile(`^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$`), 129 } 130} 131 132// ValidateIP 验证IP地址格式 133func (c *SubnetCalculator) ValidateIP(ip string) bool { 134 return c.ipRegex.MatchString(ip) 135} 136 137// ValidateCIDR 验证CIDR格式 138func (c *SubnetCalculator) ValidateCIDR(cidr string) bool { 139 return c.cidrRegex.MatchString(cidr) 140} 141 142// IPToInt IP地址转换为整数 143func (c *SubnetCalculator) IPToInt(ip string) (uint32, error) { 144 if !c.ValidateIP(ip) { 145 return 0, fmt.Errorf("无效的IP地址格式") 146 } 147 148 parts := strings.Split(ip, ".") 149 var result uint32 150 for i, part := range parts { 151 num, err := strconv.Atoi(part) 152 if err != nil { 153 return 0, err 154 } 155 result |= uint32(num) << ((3 - i) * 8) 156 } 157 return result, nil 158} 159 160// IntToIP 整数转换为IP地址 161func (c *SubnetCalculator) IntToIP(ipInt uint32) string { 162 return fmt.Sprintf("%d.%d.%d.%d", 163 (ipInt>>24)&255, 164 (ipInt>>16)&255, 165 (ipInt>>8)&255, 166 ipInt&255) 167} 168 169// GetSubnetMask 获取子网掩码 170func (c *SubnetCalculator) GetSubnetMask(cidr int) string { 171 mask := uint32(0xFFFFFFFF) << (32 - cidr) 172 return c.IntToIP(mask) 173} 174 175// GetNetworkAddress 获取网络地址 176func (c *SubnetCalculator) GetNetworkAddress(ip string, cidr int) (string, error) { 177 ipInt, err := c.IPToInt(ip) 178 if err != nil { 179 return "", err 180 } 181 mask := uint32(0xFFFFFFFF) << (32 - cidr) 182 networkInt := ipInt & mask 183 return c.IntToIP(networkInt), nil 184} 185 186// GetBroadcastAddress 获取广播地址 187func (c *SubnetCalculator) GetBroadcastAddress(ip string, cidr int) (string, error) { 188 ipInt, err := c.IPToInt(ip) 189 if err != nil { 190 return "", err 191 } 192 mask := uint32(0xFFFFFFFF) << (32 - cidr) 193 broadcastInt := ipInt | ^mask 194 return c.IntToIP(broadcastInt), nil 195} 196 197// GetFirstHost 获取第一个可用主机地址 198func (c *SubnetCalculator) GetFirstHost(ip string, cidr int) (string, error) { 199 networkIP, err := c.GetNetworkAddress(ip, cidr) 200 if err != nil { 201 return "", err 202 } 203 networkInt, err := c.IPToInt(networkIP) 204 if err != nil { 205 return "", err 206 } 207 return c.IntToIP(networkInt + 1), nil 208} 209 210// GetLastHost 获取最后一个可用主机地址 211func (c *SubnetCalculator) GetLastHost(ip string, cidr int) (string, error) { 212 broadcastIP, err := c.GetBroadcastAddress(ip, cidr) 213 if err != nil { 214 return "", err 215 } 216 broadcastInt, err := c.IPToInt(broadcastIP) 217 if err != nil { 218 return "", err 219 } 220 return c.IntToIP(broadcastInt - 1), nil 221} 222 223// GetUsableHosts 计算可用主机数量 224func (c *SubnetCalculator) GetUsableHosts(cidr int) int { 225 return int(math.Pow(2, float64(32-cidr))) - 2 226} 227 228// ParseCIDR 解析CIDR格式 229func (c *SubnetCalculator) ParseCIDR(cidr string) (string, int, error) { 230 if !c.ValidateCIDR(cidr) { 231 return "", 0, fmt.Errorf("无效的CIDR格式") 232 } 233 234 parts := strings.Split(cidr, "/") 235 ip := parts[0] 236 maskBits, err := strconv.Atoi(parts[1]) 237 if err != nil { 238 return "", 0, err 239 } 240 return ip, maskBits, nil 241} 242 243// CalculateVLSM VLSM子网划分 244func (c *SubnetCalculator) CalculateVLSM(networkCIDR string, subnetRequirements []SubnetRequirement, options map[string]interface{}) (*VLSMResult, error) { 245 networkIP, networkCIDRBits, err := c.ParseCIDR(networkCIDR) 246 if err != nil { 247 return nil, err 248 } 249 250 networkAddress, err := c.GetNetworkAddress(networkIP, networkCIDRBits) 251 if err != nil { 252 return nil, err 253 } 254 255 networkInt, err := c.IPToInt(networkAddress) 256 if err != nil { 257 return nil, err 258 } 259 260 totalHosts := c.GetUsableHosts(networkCIDRBits) 261 262 // 按主机数量排序(如果需要) 263 sortedRequirements := make([]SubnetRequirement, len(subnetRequirements)) 264 copy(sortedRequirements, subnetRequirements) 265 266 if optimizeOrder, ok := options["optimize_order"].(bool); ok && optimizeOrder { 267 sort.Slice(sortedRequirements, func(i, j int) bool { 268 return sortedRequirements[i].Hosts > sortedRequirements[j].Hosts 269 }) 270 } 271 272 // 计算每个子网需要的掩码位数 273 var subnets []SubnetInfo 274 currentNetworkInt := networkInt 275 276 for _, requirement := range sortedRequirements { 277 requiredHosts := requirement.Hosts 278 if includeNetworkBroadcast, ok := options["include_network_broadcast"].(bool); ok && includeNetworkBroadcast { 279 requiredHosts += 2 280 } 281 282 requiredCIDR := 32 - int(math.Ceil(math.Log2(float64(requiredHosts)))) 283 284 if requiredCIDR < networkCIDRBits { 285 return nil, fmt.Errorf("子网 %s 需要的主机数超出可用空间", requirement.Name) 286 } 287 288 subnetNetworkIP := c.IntToIP(currentNetworkInt) 289 subnetMask := c.GetSubnetMask(requiredCIDR) 290 subnetHosts := c.GetUsableHosts(requiredCIDR) 291 292 firstHost, _ := c.GetFirstHost(subnetNetworkIP, requiredCIDR) 293 lastHost, _ := c.GetLastHost(subnetNetworkIP, requiredCIDR) 294 broadcastAddress, _ := c.GetBroadcastAddress(subnetNetworkIP, requiredCIDR) 295 296 subnets = append(subnets, SubnetInfo{ 297 Name: requirement.Name, 298 NetworkAddress: subnetNetworkIP, 299 SubnetMask: subnetMask, 300 CIDR: requiredCIDR, 301 FirstHost: firstHost, 302 LastHost: lastHost, 303 BroadcastAddress: broadcastAddress, 304 UsableHosts: subnetHosts, 305 RequiredHosts: requirement.Hosts, 306 }) 307 308 // 计算下一个子网的起始地址 309 subnetSize := uint32(math.Pow(2, float64(32-requiredCIDR))) 310 currentNetworkInt += subnetSize 311 } 312 313 // 计算汇总信息 314 totalRequiredHosts := 0 315 for _, req := range sortedRequirements { 316 totalRequiredHosts += req.Hosts 317 } 318 utilization := float64(totalRequiredHosts) / float64(totalHosts) * 100 319 320 return &VLSMResult{ 321 Subnets: subnets, 322 Summary: SummaryInfo{ 323 OriginalNetwork: networkCIDR, 324 TotalSubnets: len(subnets), 325 TotalHosts: totalRequiredHosts, 326 Utilization: utilization, 327 }, 328 Details: fmt.Sprintf("VLSM划分完成,共创建 %d 个子网,地址利用率 %.2f%%", len(subnets), utilization), 329 }, nil 330} 331 332// MergeSubnets 子网合并 333func (c *SubnetCalculator) MergeSubnets(subnetList []string, options map[string]interface{}) (*MergeResult, error) { 334 var subnets []struct { 335 Network string 336 NetworkIP string 337 CIDR int 338 NetworkInt uint32 339 HostCount int 340 } 341 342 // 解析子网列表 343 for _, subnetStr := range subnetList { 344 if !c.ValidateCIDR(subnetStr) { 345 if validateSubnets, ok := options["validate_subnets"].(bool); ok && validateSubnets { 346 return nil, fmt.Errorf("无效的子网格式: %s", subnetStr) 347 } 348 continue 349 } 350 351 ip, cidr, err := c.ParseCIDR(subnetStr) 352 if err != nil { 353 continue 354 } 355 356 networkIP, err := c.GetNetworkAddress(ip, cidr) 357 if err != nil { 358 continue 359 } 360 361 networkInt, err := c.IPToInt(networkIP) 362 if err != nil { 363 continue 364 } 365 366 subnets = append(subnets, struct { 367 Network string 368 NetworkIP string 369 CIDR int 370 NetworkInt uint32 371 HostCount int 372 }{ 373 Network: subnetStr, 374 NetworkIP: networkIP, 375 CIDR: cidr, 376 NetworkInt: networkInt, 377 HostCount: c.GetUsableHosts(cidr), 378 }) 379 } 380 381 if len(subnets) == 0 { 382 return nil, fmt.Errorf("没有有效的子网可以合并") 383 } 384 385 // 按网络地址排序 386 sort.Slice(subnets, func(i, j int) bool { 387 return subnets[i].NetworkInt < subnets[j].NetworkInt 388 }) 389 390 var mergedSubnets []MergedSubnet 391 currentGroup := []struct { 392 Network string 393 NetworkIP string 394 CIDR int 395 NetworkInt uint32 396 HostCount int 397 }{subnets[0]} 398 399 for i := 1; i < len(subnets); i++ { 400 current := subnets[i] 401 last := currentGroup[len(currentGroup)-1] 402 403 // 检查是否相邻或连续 404 isAdjacent := false 405 isContiguous := false 406 407 if mergeAdjacent, ok := options["merge_adjacent"].(bool); ok && mergeAdjacent { 408 isAdjacent = c.areSubnetsAdjacent(last, current) 409 } 410 411 if mergeContiguous, ok := options["merge_contiguous"].(bool); ok && mergeContiguous { 412 isContiguous = c.areSubnetsContiguous(last, current) 413 } 414 415 if isAdjacent || isContiguous { 416 currentGroup = append(currentGroup, current) 417 } else { 418 // 合并当前组 419 if len(currentGroup) > 1 { 420 mergedSubnets = append(mergedSubnets, c.mergeSubnetGroup(currentGroup)) 421 } else { 422 mergedSubnets = append(mergedSubnets, MergedSubnet{ 423 Network: currentGroup[0].Network, 424 OriginalSubnets: []string{currentGroup[0].Network}, 425 HostCount: currentGroup[0].HostCount, 426 }) 427 } 428 currentGroup = []struct { 429 Network string 430 NetworkIP string 431 CIDR int 432 NetworkInt uint32 433 HostCount int 434 }{current} 435 } 436 } 437 438 // 处理最后一组 439 if len(currentGroup) > 1 { 440 mergedSubnets = append(mergedSubnets, c.mergeSubnetGroup(currentGroup)) 441 } else { 442 mergedSubnets = append(mergedSubnets, MergedSubnet{ 443 Network: currentGroup[0].Network, 444 OriginalSubnets: []string{currentGroup[0].Network}, 445 HostCount: currentGroup[0].HostCount, 446 }) 447 } 448 449 // 计算汇总信息 450 originalCount := len(subnets) 451 mergedCount := len(mergedSubnets) 452 reduction := originalCount - mergedCount 453 totalHosts := 0 454 for _, subnet := range mergedSubnets { 455 totalHosts += subnet.HostCount 456 } 457 458 return &MergeResult{ 459 MergedSubnets: mergedSubnets, 460 Summary: MergeSummary{ 461 OriginalCount: originalCount, 462 MergedCount: mergedCount, 463 Reduction: reduction, 464 TotalHosts: totalHosts, 465 Utilization: float64(totalHosts) / float64(0xFFFFFFFF) * 100, 466 }, 467 Details: fmt.Sprintf("合并完成,从 %d 个子网合并为 %d 个,减少 %d 个", originalCount, mergedCount, reduction), 468 }, nil 469} 470 471// areSubnetsAdjacent 检查两个子网是否相邻 472func (c *SubnetCalculator) areSubnetsAdjacent(subnet1, subnet2 struct { 473 Network string 474 NetworkIP string 475 CIDR int 476 NetworkInt uint32 477 HostCount int 478}) bool { 479 broadcast1, _ := c.GetBroadcastAddress(subnet1.NetworkIP, subnet1.CIDR) 480 broadcast1Int, _ := c.IPToInt(broadcast1) 481 return subnet2.NetworkInt == broadcast1Int+1 482} 483 484// areSubnetsContiguous 检查两个子网是否连续 485func (c *SubnetCalculator) areSubnetsContiguous(subnet1, subnet2 struct { 486 Network string 487 NetworkIP string 488 CIDR int 489 NetworkInt uint32 490 HostCount int 491}) bool { 492 broadcast1, _ := c.GetBroadcastAddress(subnet1.NetworkIP, subnet1.CIDR) 493 broadcast1Int, _ := c.IPToInt(broadcast1) 494 return subnet2.NetworkInt <= broadcast1Int+1 495} 496 497// mergeSubnetGroup 合并子网组 498func (c *SubnetCalculator) mergeSubnetGroup(subnetGroup []struct { 499 Network string 500 NetworkIP string 501 CIDR int 502 NetworkInt uint32 503 HostCount int 504}) MergedSubnet { 505 first := subnetGroup[0] 506 last := subnetGroup[len(subnetGroup)-1] 507 lastBroadcast, _ := c.GetBroadcastAddress(last.NetworkIP, last.CIDR) 508 lastBroadcastInt, _ := c.IPToInt(lastBroadcast) 509 510 // 计算合并后的CIDR 511 rangeSize := lastBroadcastInt - first.NetworkInt + 1 512 mergedCIDR := 32 - int(math.Ceil(math.Log2(float64(rangeSize)))) 513 514 mergedNetworkIP := c.IntToIP(first.NetworkInt) 515 mergedNetwork := fmt.Sprintf("%s/%d", mergedNetworkIP, mergedCIDR) 516 mergedHostCount := c.GetUsableHosts(mergedCIDR) 517 518 var originalSubnets []string 519 for _, subnet := range subnetGroup { 520 originalSubnets = append(originalSubnets, subnet.Network) 521 } 522 523 return MergedSubnet{ 524 Network: mergedNetwork, 525 OriginalSubnets: originalSubnets, 526 HostCount: mergedHostCount, 527 } 528} 529 530// CalculateSupernet 超网计算 531func (c *SubnetCalculator) CalculateSupernet(startIP, endIP string, options map[string]interface{}) (*SupernetResult, error) { 532 if !c.ValidateIP(startIP) || !c.ValidateIP(endIP) { 533 return nil, fmt.Errorf("无效的IP地址格式") 534 } 535 536 startInt, err := c.IPToInt(startIP) 537 if err != nil { 538 return nil, err 539 } 540 541 endInt, err := c.IPToInt(endIP) 542 if err != nil { 543 return nil, err 544 } 545 546 if startInt > endInt { 547 return nil, fmt.Errorf("起始IP不能大于结束IP") 548 } 549 550 // 计算包含该范围的最小超网 551 rangeSize := endInt - startInt + 1 552 requiredCIDR := 32 - int(math.Ceil(math.Log2(float64(rangeSize)))) 553 554 // 找到包含该范围的最小网络地址 555 mask := uint32(0xFFFFFFFF) << (32 - requiredCIDR) 556 networkInt := startInt & mask 557 networkIP := c.IntToIP(networkInt) 558 559 // 验证该网络是否包含整个范围 560 broadcastInt := networkInt | ^mask 561 if broadcastInt < endInt { 562 // 需要更大的网络 563 newCIDR := requiredCIDR - 1 564 newMask := uint32(0xFFFFFFFF) << (32 - newCIDR) 565 newNetworkInt := startInt & newMask 566 newNetworkIP := c.IntToIP(newNetworkInt) 567 568 return &SupernetResult{ 569 NetworkAddress: newNetworkIP, 570 SubnetMask: c.GetSubnetMask(newCIDR), 571 CIDR: newCIDR, 572 BroadcastAddress: c.IntToIP(newNetworkInt | ^newMask), 573 FirstHost: c.IntToIP(newNetworkInt + 1), 574 LastHost: c.IntToIP((newNetworkInt | ^newMask) - 1), 575 TotalHosts: c.GetUsableHosts(newCIDR), 576 StartIP: startIP, 577 EndIP: endIP, 578 Details: fmt.Sprintf("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, newNetworkIP, newCIDR), 579 }, nil 580 } 581 582 return &SupernetResult{ 583 NetworkAddress: networkIP, 584 SubnetMask: c.GetSubnetMask(requiredCIDR), 585 CIDR: requiredCIDR, 586 BroadcastAddress: c.IntToIP(broadcastInt), 587 FirstHost: c.IntToIP(networkInt + 1), 588 LastHost: c.IntToIP(broadcastInt - 1), 589 TotalHosts: c.GetUsableHosts(requiredCIDR), 590 StartIP: startIP, 591 EndIP: endIP, 592 Details: fmt.Sprintf("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, networkIP, requiredCIDR), 593 }, nil 594} 595 596// GenerateNetworkPlan 网络规划 597func (c *SubnetCalculator) GenerateNetworkPlan(addressSpace string, departmentRequirements []DepartmentRequirement, options map[string]interface{}) (*PlanningResult, error) { 598 networkIP, networkCIDRBits, err := c.ParseCIDR(addressSpace) 599 if err != nil { 600 return nil, err 601 } 602 603 networkAddress, err := c.GetNetworkAddress(networkIP, networkCIDRBits) 604 if err != nil { 605 return nil, err 606 } 607 608 networkInt, err := c.IPToInt(networkAddress) 609 if err != nil { 610 return nil, err 611 } 612 613 totalSpace := c.GetUsableHosts(networkCIDRBits) 614 615 // 按部门大小排序 616 sortedDepartments := make([]DepartmentRequirement, len(departmentRequirements)) 617 copy(sortedDepartments, departmentRequirements) 618 619 if optimizeUtilization, ok := options["optimize_utilization"].(bool); ok && optimizeUtilization { 620 sort.Slice(sortedDepartments, func(i, j int) bool { 621 return sortedDepartments[i].Size > sortedDepartments[j].Size 622 }) 623 } 624 625 var departments []DepartmentInfo 626 currentNetworkInt := networkInt 627 allocatedSpace := 0 628 629 for _, dept := range sortedDepartments { 630 requiredHosts := dept.Size 631 if reserveSpace, ok := options["reserve_space"].(bool); ok && reserveSpace { 632 requiredHosts += int(float64(dept.Size) * 0.2) 633 } 634 635 requiredCIDR := 32 - int(math.Ceil(math.Log2(float64(requiredHosts+2)))) // +2 for network and broadcast 636 637 if requiredCIDR < networkCIDRBits { 638 return nil, fmt.Errorf("部门 %s 需要的主机数超出可用空间", dept.Name) 639 } 640 641 deptNetworkIP := c.IntToIP(currentNetworkInt) 642 deptSubnetMask := c.GetSubnetMask(requiredCIDR) 643 deptHosts := c.GetUsableHosts(requiredCIDR) 644 645 firstHost, _ := c.GetFirstHost(deptNetworkIP, requiredCIDR) 646 lastHost, _ := c.GetLastHost(deptNetworkIP, requiredCIDR) 647 648 departments = append(departments, DepartmentInfo{ 649 Name: dept.Name, 650 NetworkAddress: deptNetworkIP, 651 SubnetMask: deptSubnetMask, 652 CIDR: requiredCIDR, 653 FirstHost: firstHost, 654 LastHost: lastHost, 655 AllocatedHosts: dept.Size, 656 TotalHosts: deptHosts, 657 }) 658 659 allocatedSpace += deptHosts 660 subnetSize := uint32(math.Pow(2, float64(32-requiredCIDR))) 661 currentNetworkInt += subnetSize 662 } 663 664 remainingSpace := totalSpace - allocatedSpace 665 utilization := float64(allocatedSpace) / float64(totalSpace) * 100 666 667 return &PlanningResult{ 668 Departments: departments, 669 Summary: PlanningSummary{ 670 TotalSpace: totalSpace, 671 AllocatedSpace: allocatedSpace, 672 RemainingSpace: remainingSpace, 673 Utilization: utilization, 674 DepartmentCount: len(departments), 675 }, 676 Details: fmt.Sprintf("网络规划完成,共分配 %d 个部门,地址利用率 %.2f%%,剩余空间 %d 个主机", len(departments), utilization, remainingSpace), 677 }, nil 678} 679 680// GetSubnetInfo 获取子网详细信息(使用net包) 681func (c *SubnetCalculator) GetSubnetInfo(ip string, cidr int) (map[string]interface{}, error) { 682 _, network, err := net.ParseCIDR(fmt.Sprintf("%s/%d", ip, cidr)) 683 if err != nil { 684 return nil, fmt.Errorf("无法解析子网信息: %v", err) 685 } 686 687 ones, bits := network.Mask.Size() 688 networkAddress := network.IP.String() 689 690 // 计算广播地址 691 broadcast := make(net.IP, len(network.IP)) 692 copy(broadcast, network.IP) 693 for i := range broadcast { 694 broadcast[i] |= ^network.Mask[i] 695 } 696 697 // 计算第一个和最后一个主机地址 698 firstHost := make(net.IP, len(network.IP)) 699 copy(firstHost, network.IP) 700 firstHost[len(firstHost)-1]++ 701 702 lastHost := make(net.IP, len(broadcast)) 703 copy(lastHost, broadcast) 704 lastHost[len(lastHost)-1]-- 705 706 return map[string]interface{}{ 707 "network_address": networkAddress, 708 "broadcast_address": broadcast.String(), 709 "subnet_mask": net.IP(network.Mask).String(), 710 "num_addresses": int(math.Pow(2, float64(bits-ones))), 711 "usable_hosts": int(math.Pow(2, float64(bits-ones))) - 2, 712 "first_host": firstHost.String(), 713 "last_host": lastHost.String(), 714 }, nil 715} 716 717func main() { 718 calculator := NewSubnetCalculator() 719 720 fmt.Println("=== 子网划分工具 - Go版本 ===") 721 722 // VLSM示例 723 fmt.Println("\n--- VLSM子网划分示例 ---") 724 vlsmResult, err := calculator.CalculateVLSM("192.168.1.0/24", []SubnetRequirement{ 725 {Name: "销售部", Hosts: 50}, 726 {Name: "技术部", Hosts: 30}, 727 {Name: "财务部", Hosts: 10}, 728 {Name: "人事部", Hosts: 5}, 729 }, map[string]interface{}{ 730 "optimize_order": true, 731 "include_network_broadcast": true, 732 }) 733 if err != nil { 734 fmt.Printf("VLSM错误: %v\n", err) 735 } else { 736 fmt.Println("VLSM结果:") 737 for _, subnet := range vlsmResult.Subnets { 738 fmt.Printf(" %s: %s/%d (%s - %s)\n", subnet.Name, subnet.NetworkAddress, subnet.CIDR, subnet.FirstHost, subnet.LastHost) 739 } 740 fmt.Printf("汇总: %+v\n", vlsmResult.Summary) 741 } 742 743 // 子网合并示例 744 fmt.Println("\n--- 子网合并示例 ---") 745 mergeResult, err := calculator.MergeSubnets([]string{ 746 "192.168.1.0/26", 747 "192.168.1.64/26", 748 "192.168.1.128/26", 749 "192.168.1.192/26", 750 }, map[string]interface{}{ 751 "merge_adjacent": true, 752 "merge_contiguous": true, 753 "validate_subnets": true, 754 }) 755 if err != nil { 756 fmt.Printf("合并错误: %v\n", err) 757 } else { 758 fmt.Println("合并结果:") 759 for _, merged := range mergeResult.MergedSubnets { 760 fmt.Printf(" %s (包含: %s)\n", merged.Network, strings.Join(merged.OriginalSubnets, ", ")) 761 } 762 fmt.Printf("汇总: %+v\n", mergeResult.Summary) 763 } 764 765 // 超网计算示例 766 fmt.Println("\n--- 超网计算示例 ---") 767 supernetResult, err := calculator.CalculateSupernet("192.168.1.10", "192.168.1.50", nil) 768 if err != nil { 769 fmt.Printf("超网错误: %v\n", err) 770 } else { 771 fmt.Printf("超网结果: %s/%d\n", supernetResult.NetworkAddress, supernetResult.CIDR) 772 fmt.Printf("详细信息: %+v\n", supernetResult) 773 } 774 775 // 网络规划示例 776 fmt.Println("\n--- 网络规划示例 ---") 777 planningResult, err := calculator.GenerateNetworkPlan("10.0.0.0/8", []DepartmentRequirement{ 778 {Name: "总部", Size: 200}, 779 {Name: "分公司A", Size: 100}, 780 {Name: "分公司B", Size: 80}, 781 {Name: "研发中心", Size: 150}, 782 }, map[string]interface{}{ 783 "optimize_utilization": true, 784 "reserve_space": true, 785 }) 786 if err != nil { 787 fmt.Printf("规划错误: %v\n", err) 788 } else { 789 fmt.Println("规划结果:") 790 for _, dept := range planningResult.Departments { 791 fmt.Printf(" %s: %s/%d (%d 主机)\n", dept.Name, dept.NetworkAddress, dept.CIDR, dept.AllocatedHosts) 792 } 793 fmt.Printf("汇总: %+v\n", planningResult.Summary) 794 } 795}
-
subnet_calculator (JAVA)
1import java.util.*; 2import java.util.regex.Pattern; 3import java.util.regex.Matcher; 4 5/** 6 * 子网划分工具 - Java版本 7 * 支持VLSM可变长子网掩码、子网合并、超网计算、网络规划等功能 8 */ 9public class SubnetCalculator { 10 private static final Pattern IP_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"); 11 private static final Pattern CIDR_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/([0-9]|[1-2][0-9]|3[0-2])$"); 12 13 // 子网需求类 14 public static class SubnetRequirement { 15 private String name; 16 private int hosts; 17 18 public SubnetRequirement(String name, int hosts) { 19 this.name = name; 20 this.hosts = hosts; 21 } 22 23 public String getName() { return name; } 24 public int getHosts() { return hosts; } 25 } 26 27 // 部门需求类 28 public static class DepartmentRequirement { 29 private String name; 30 private int size; 31 32 public DepartmentRequirement(String name, int size) { 33 this.name = name; 34 this.size = size; 35 } 36 37 public String getName() { return name; } 38 public int getSize() { return size; } 39 } 40 41 // VLSM结果类 42 public static class VLSMResult { 43 private List<SubnetInfo> subnets; 44 private SummaryInfo summary; 45 private String details; 46 47 public VLSMResult(List<SubnetInfo> subnets, SummaryInfo summary, String details) { 48 this.subnets = subnets; 49 this.summary = summary; 50 this.details = details; 51 } 52 53 public List<SubnetInfo> getSubnets() { return subnets; } 54 public SummaryInfo getSummary() { return summary; } 55 public String getDetails() { return details; } 56 } 57 58 // 子网信息类 59 public static class SubnetInfo { 60 private String name; 61 private String networkAddress; 62 private String subnetMask; 63 private int cidr; 64 private String firstHost; 65 private String lastHost; 66 private String broadcastAddress; 67 private int usableHosts; 68 private int requiredHosts; 69 70 public SubnetInfo(String name, String networkAddress, String subnetMask, int cidr, 71 String firstHost, String lastHost, String broadcastAddress, 72 int usableHosts, int requiredHosts) { 73 this.name = name; 74 this.networkAddress = networkAddress; 75 this.subnetMask = subnetMask; 76 this.cidr = cidr; 77 this.firstHost = firstHost; 78 this.lastHost = lastHost; 79 this.broadcastAddress = broadcastAddress; 80 this.usableHosts = usableHosts; 81 this.requiredHosts = requiredHosts; 82 } 83 84 // Getters 85 public String getName() { return name; } 86 public String getNetworkAddress() { return networkAddress; } 87 public String getSubnetMask() { return subnetMask; } 88 public int getCidr() { return cidr; } 89 public String getFirstHost() { return firstHost; } 90 public String getLastHost() { return lastHost; } 91 public String getBroadcastAddress() { return broadcastAddress; } 92 public int getUsableHosts() { return usableHosts; } 93 public int getRequiredHosts() { return requiredHosts; } 94 } 95 96 // 汇总信息类 97 public static class SummaryInfo { 98 private String originalNetwork; 99 private int totalSubnets; 100 private int totalHosts; 101 private double utilization; 102 103 public SummaryInfo(String originalNetwork, int totalSubnets, int totalHosts, double utilization) { 104 this.originalNetwork = originalNetwork; 105 this.totalSubnets = totalSubnets; 106 this.totalHosts = totalHosts; 107 this.utilization = utilization; 108 } 109 110 // Getters 111 public String getOriginalNetwork() { return originalNetwork; } 112 public int getTotalSubnets() { return totalSubnets; } 113 public int getTotalHosts() { return totalHosts; } 114 public double getUtilization() { return utilization; } 115 } 116 117 // 合并结果类 118 public static class MergeResult { 119 private List<MergedSubnet> mergedSubnets; 120 private MergeSummary summary; 121 private String details; 122 123 public MergeResult(List<MergedSubnet> mergedSubnets, MergeSummary summary, String details) { 124 this.mergedSubnets = mergedSubnets; 125 this.summary = summary; 126 this.details = details; 127 } 128 129 public List<MergedSubnet> getMergedSubnets() { return mergedSubnets; } 130 public MergeSummary getSummary() { return summary; } 131 public String getDetails() { return details; } 132 } 133 134 // 合并后的子网类 135 public static class MergedSubnet { 136 private String network; 137 private List<String> originalSubnets; 138 private int hostCount; 139 140 public MergedSubnet(String network, List<String> originalSubnets, int hostCount) { 141 this.network = network; 142 this.originalSubnets = originalSubnets; 143 this.hostCount = hostCount; 144 } 145 146 // Getters 147 public String getNetwork() { return network; } 148 public List<String> getOriginalSubnets() { return originalSubnets; } 149 public int getHostCount() { return hostCount; } 150 } 151 152 // 合并汇总信息类 153 public static class MergeSummary { 154 private int originalCount; 155 private int mergedCount; 156 private int reduction; 157 private int totalHosts; 158 private double utilization; 159 160 public MergeSummary(int originalCount, int mergedCount, int reduction, int totalHosts, double utilization) { 161 this.originalCount = originalCount; 162 this.mergedCount = mergedCount; 163 this.reduction = reduction; 164 this.totalHosts = totalHosts; 165 this.utilization = utilization; 166 } 167 168 // Getters 169 public int getOriginalCount() { return originalCount; } 170 public int getMergedCount() { return mergedCount; } 171 public int getReduction() { return reduction; } 172 public int getTotalHosts() { return totalHosts; } 173 public double getUtilization() { return utilization; } 174 } 175 176 // 超网结果类 177 public static class SupernetResult { 178 private String networkAddress; 179 private String subnetMask; 180 private int cidr; 181 private String broadcastAddress; 182 private String firstHost; 183 private String lastHost; 184 private int totalHosts; 185 private String startIP; 186 private String endIP; 187 private String details; 188 189 public SupernetResult(String networkAddress, String subnetMask, int cidr, 190 String broadcastAddress, String firstHost, String lastHost, 191 int totalHosts, String startIP, String endIP, String details) { 192 this.networkAddress = networkAddress; 193 this.subnetMask = subnetMask; 194 this.cidr = cidr; 195 this.broadcastAddress = broadcastAddress; 196 this.firstHost = firstHost; 197 this.lastHost = lastHost; 198 this.totalHosts = totalHosts; 199 this.startIP = startIP; 200 this.endIP = endIP; 201 this.details = details; 202 } 203 204 // Getters 205 public String getNetworkAddress() { return networkAddress; } 206 public String getSubnetMask() { return subnetMask; } 207 public int getCidr() { return cidr; } 208 public String getBroadcastAddress() { return broadcastAddress; } 209 public String getFirstHost() { return firstHost; } 210 public String getLastHost() { return lastHost; } 211 public int getTotalHosts() { return totalHosts; } 212 public String getStartIP() { return startIP; } 213 public String getEndIP() { return endIP; } 214 public String getDetails() { return details; } 215 } 216 217 // 规划结果类 218 public static class PlanningResult { 219 private List<DepartmentInfo> departments; 220 private PlanningSummary summary; 221 private String details; 222 223 public PlanningResult(List<DepartmentInfo> departments, PlanningSummary summary, String details) { 224 this.departments = departments; 225 this.summary = summary; 226 this.details = details; 227 } 228 229 public List<DepartmentInfo> getDepartments() { return departments; } 230 public PlanningSummary getSummary() { return summary; } 231 public String getDetails() { return details; } 232 } 233 234 // 部门信息类 235 public static class DepartmentInfo { 236 private String name; 237 private String networkAddress; 238 private String subnetMask; 239 private int cidr; 240 private String firstHost; 241 private String lastHost; 242 private int allocatedHosts; 243 private int totalHosts; 244 245 public DepartmentInfo(String name, String networkAddress, String subnetMask, int cidr, 246 String firstHost, String lastHost, int allocatedHosts, int totalHosts) { 247 this.name = name; 248 this.networkAddress = networkAddress; 249 this.subnetMask = subnetMask; 250 this.cidr = cidr; 251 this.firstHost = firstHost; 252 this.lastHost = lastHost; 253 this.allocatedHosts = allocatedHosts; 254 this.totalHosts = totalHosts; 255 } 256 257 // Getters 258 public String getName() { return name; } 259 public String getNetworkAddress() { return networkAddress; } 260 public String getSubnetMask() { return subnetMask; } 261 public int getCidr() { return cidr; } 262 public String getFirstHost() { return firstHost; } 263 public String getLastHost() { return lastHost; } 264 public int getAllocatedHosts() { return allocatedHosts; } 265 public int getTotalHosts() { return totalHosts; } 266 } 267 268 // 规划汇总信息类 269 public static class PlanningSummary { 270 private int totalSpace; 271 private int allocatedSpace; 272 private int remainingSpace; 273 private double utilization; 274 private int departmentCount; 275 276 public PlanningSummary(int totalSpace, int allocatedSpace, int remainingSpace, 277 double utilization, int departmentCount) { 278 this.totalSpace = totalSpace; 279 this.allocatedSpace = allocatedSpace; 280 this.remainingSpace = remainingSpace; 281 this.utilization = utilization; 282 this.departmentCount = departmentCount; 283 } 284 285 // Getters 286 public int getTotalSpace() { return totalSpace; } 287 public int getAllocatedSpace() { return allocatedSpace; } 288 public int getRemainingSpace() { return remainingSpace; } 289 public double getUtilization() { return utilization; } 290 public int getDepartmentCount() { return departmentCount; } 291 } 292 293 /** 294 * 验证IP地址格式 295 */ 296 public boolean validateIP(String ip) { 297 return IP_PATTERN.matcher(ip).matches(); 298 } 299 300 /** 301 * 验证CIDR格式 302 */ 303 public boolean validateCIDR(String cidr) { 304 return CIDR_PATTERN.matcher(cidr).matches(); 305 } 306 307 /** 308 * IP地址转换为长整数 309 */ 310 public long ipToLong(String ip) throws IllegalArgumentException { 311 if (!validateIP(ip)) { 312 throw new IllegalArgumentException("无效的IP地址格式"); 313 } 314 315 String[] parts = ip.split("\\."); 316 long result = 0; 317 for (int i = 0; i < 4; i++) { 318 result = result << 8 | Integer.parseInt(parts[i]); 319 } 320 return result; 321 } 322 323 /** 324 * 长整数转换为IP地址 325 */ 326 public String longToIP(long ipLong) { 327 return String.format("%d.%d.%d.%d", 328 (ipLong >> 24) & 0xFF, 329 (ipLong >> 16) & 0xFF, 330 (ipLong >> 8) & 0xFF, 331 ipLong & 0xFF); 332 } 333 334 /** 335 * 获取子网掩码 336 */ 337 public String getSubnetMask(int cidr) { 338 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 339 return longToIP(mask); 340 } 341 342 /** 343 * 获取网络地址 344 */ 345 public String getNetworkAddress(String ip, int cidr) throws IllegalArgumentException { 346 long ipLong = ipToLong(ip); 347 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 348 long networkLong = ipLong & mask; 349 return longToIP(networkLong); 350 } 351 352 /** 353 * 获取广播地址 354 */ 355 public String getBroadcastAddress(String ip, int cidr) throws IllegalArgumentException { 356 long ipLong = ipToLong(ip); 357 long mask = (0xFFFFFFFFL << (32 - cidr)) & 0xFFFFFFFFL; 358 long broadcastLong = ipLong | (~mask & 0xFFFFFFFFL); 359 return longToIP(broadcastLong); 360 } 361 362 /** 363 * 获取第一个可用主机地址 364 */ 365 public String getFirstHost(String ip, int cidr) throws IllegalArgumentException { 366 String networkIP = getNetworkAddress(ip, cidr); 367 long networkLong = ipToLong(networkIP); 368 return longToIP(networkLong + 1); 369 } 370 371 /** 372 * 获取最后一个可用主机地址 373 */ 374 public String getLastHost(String ip, int cidr) throws IllegalArgumentException { 375 String broadcastIP = getBroadcastAddress(ip, cidr); 376 long broadcastLong = ipToLong(broadcastIP); 377 return longToIP(broadcastLong - 1); 378 } 379 380 /** 381 * 计算可用主机数量 382 */ 383 public int getUsableHosts(int cidr) { 384 return (int) (Math.pow(2, 32 - cidr) - 2); 385 } 386 387 /** 388 * 解析CIDR格式 389 */ 390 public String[] parseCIDR(String cidr) throws IllegalArgumentException { 391 if (!validateCIDR(cidr)) { 392 throw new IllegalArgumentException("无效的CIDR格式"); 393 } 394 395 String[] parts = cidr.split("/"); 396 return new String[]{parts[0], parts[1]}; 397 } 398 399 /** 400 * VLSM子网划分 401 */ 402 public VLSMResult calculateVLSM(String networkCIDR, List<SubnetRequirement> subnetRequirements, 403 Map<String, Object> options) throws IllegalArgumentException { 404 String[] parsed = parseCIDR(networkCIDR); 405 String networkIP = parsed[0]; 406 int networkCIDRBits = Integer.parseInt(parsed[1]); 407 408 String networkAddress = getNetworkAddress(networkIP, networkCIDRBits); 409 long networkLong = ipToLong(networkAddress); 410 int totalHosts = getUsableHosts(networkCIDRBits); 411 412 // 按主机数量排序(如果需要) 413 List<SubnetRequirement> sortedRequirements = new ArrayList<>(subnetRequirements); 414 if (options != null && options.containsKey("optimize_order") && 415 (Boolean) options.get("optimize_order")) { 416 sortedRequirements.sort((a, b) -> Integer.compare(b.getHosts(), a.getHosts())); 417 } 418 419 // 计算每个子网需要的掩码位数 420 List<SubnetInfo> subnets = new ArrayList<>(); 421 long currentNetworkLong = networkLong; 422 423 for (SubnetRequirement requirement : sortedRequirements) { 424 int requiredHosts = requirement.getHosts(); 425 if (options != null && options.containsKey("include_network_broadcast") && 426 (Boolean) options.get("include_network_broadcast")) { 427 requiredHosts += 2; 428 } 429 430 int requiredCIDR = 32 - (int) Math.ceil(Math.log(requiredHosts) / Math.log(2)); 431 432 if (requiredCIDR < networkCIDRBits) { 433 throw new IllegalArgumentException("子网 " + requirement.getName() + " 需要的主机数超出可用空间"); 434 } 435 436 String subnetNetworkIP = longToIP(currentNetworkLong); 437 String subnetMask = getSubnetMask(requiredCIDR); 438 int subnetHosts = getUsableHosts(requiredCIDR); 439 440 String firstHost = getFirstHost(subnetNetworkIP, requiredCIDR); 441 String lastHost = getLastHost(subnetNetworkIP, requiredCIDR); 442 String broadcastAddress = getBroadcastAddress(subnetNetworkIP, requiredCIDR); 443 444 subnets.add(new SubnetInfo( 445 requirement.getName(), 446 subnetNetworkIP, 447 subnetMask, 448 requiredCIDR, 449 firstHost, 450 lastHost, 451 broadcastAddress, 452 subnetHosts, 453 requirement.getHosts() 454 )); 455 456 // 计算下一个子网的起始地址 457 long subnetSize = (long) Math.pow(2, 32 - requiredCIDR); 458 currentNetworkLong += subnetSize; 459 } 460 461 // 计算汇总信息 462 int totalRequiredHosts = sortedRequirements.stream().mapToInt(SubnetRequirement::getHosts).sum(); 463 double utilization = (double) totalRequiredHosts / totalHosts * 100; 464 465 return new VLSMResult( 466 subnets, 467 new SummaryInfo(networkCIDR, subnets.size(), totalRequiredHosts, utilization), 468 String.format("VLSM划分完成,共创建 %d 个子网,地址利用率 %.2f%%", subnets.size(), utilization) 469 ); 470 } 471 472 /** 473 * 子网合并 474 */ 475 public MergeResult mergeSubnets(List<String> subnetList, Map<String, Object> options) 476 throws IllegalArgumentException { 477 List<SubnetData> subnets = new ArrayList<>(); 478 479 // 解析子网列表 480 for (String subnetStr : subnetList) { 481 if (!validateCIDR(subnetStr)) { 482 if (options != null && options.containsKey("validate_subnets") && 483 (Boolean) options.get("validate_subnets")) { 484 throw new IllegalArgumentException("无效的子网格式: " + subnetStr); 485 } 486 continue; 487 } 488 489 String[] parsed = parseCIDR(subnetStr); 490 String ip = parsed[0]; 491 int cidr = Integer.parseInt(parsed[1]); 492 493 String networkIP = getNetworkAddress(ip, cidr); 494 long networkLong = ipToLong(networkIP); 495 496 subnets.add(new SubnetData(subnetStr, networkIP, cidr, networkLong, getUsableHosts(cidr))); 497 } 498 499 if (subnets.isEmpty()) { 500 throw new IllegalArgumentException("没有有效的子网可以合并"); 501 } 502 503 // 按网络地址排序 504 subnets.sort(Comparator.comparingLong(SubnetData::getNetworkLong)); 505 506 List<MergedSubnet> mergedSubnets = new ArrayList<>(); 507 List<SubnetData> currentGroup = new ArrayList<>(); 508 currentGroup.add(subnets.get(0)); 509 510 for (int i = 1; i < subnets.size(); i++) { 511 SubnetData current = subnets.get(i); 512 SubnetData last = currentGroup.get(currentGroup.size() - 1); 513 514 // 检查是否相邻或连续 515 boolean isAdjacent = false; 516 boolean isContiguous = false; 517 518 if (options != null && options.containsKey("merge_adjacent") && 519 (Boolean) options.get("merge_adjacent")) { 520 isAdjacent = areSubnetsAdjacent(last, current); 521 } 522 523 if (options != null && options.containsKey("merge_contiguous") && 524 (Boolean) options.get("merge_contiguous")) { 525 isContiguous = areSubnetsContiguous(last, current); 526 } 527 528 if (isAdjacent || isContiguous) { 529 currentGroup.add(current); 530 } else { 531 // 合并当前组 532 if (currentGroup.size() > 1) { 533 mergedSubnets.add(mergeSubnetGroup(currentGroup)); 534 } else { 535 List<String> originalSubnets = new ArrayList<>(); 536 originalSubnets.add(currentGroup.get(0).getNetwork()); 537 mergedSubnets.add(new MergedSubnet( 538 currentGroup.get(0).getNetwork(), 539 originalSubnets, 540 currentGroup.get(0).getHostCount() 541 )); 542 } 543 currentGroup = new ArrayList<>(); 544 currentGroup.add(current); 545 } 546 } 547 548 // 处理最后一组 549 if (currentGroup.size() > 1) { 550 mergedSubnets.add(mergeSubnetGroup(currentGroup)); 551 } else { 552 List<String> originalSubnets = new ArrayList<>(); 553 originalSubnets.add(currentGroup.get(0).getNetwork()); 554 mergedSubnets.add(new MergedSubnet( 555 currentGroup.get(0).getNetwork(), 556 originalSubnets, 557 currentGroup.get(0).getHostCount() 558 )); 559 } 560 561 // 计算汇总信息 562 int originalCount = subnets.size(); 563 int mergedCount = mergedSubnets.size(); 564 int reduction = originalCount - mergedCount; 565 int totalHosts = mergedSubnets.stream().mapToInt(MergedSubnet::getHostCount).sum(); 566 567 return new MergeResult( 568 mergedSubnets, 569 new MergeSummary(originalCount, mergedCount, reduction, totalHosts, 570 (double) totalHosts / 0xFFFFFFFFL * 100), 571 String.format("合并完成,从 %d 个子网合并为 %d 个,减少 %d 个", originalCount, mergedCount, reduction) 572 ); 573 } 574 575 // 子网数据内部类 576 private static class SubnetData { 577 private String network; 578 private String networkIP; 579 private int cidr; 580 private long networkLong; 581 private int hostCount; 582 583 public SubnetData(String network, String networkIP, int cidr, long networkLong, int hostCount) { 584 this.network = network; 585 this.networkIP = networkIP; 586 this.cidr = cidr; 587 this.networkLong = networkLong; 588 this.hostCount = hostCount; 589 } 590 591 public String getNetwork() { return network; } 592 public String getNetworkIP() { return networkIP; } 593 public int getCidr() { return cidr; } 594 public long getNetworkLong() { return networkLong; } 595 public int getHostCount() { return hostCount; } 596 } 597 598 /** 599 * 检查两个子网是否相邻 600 */ 601 private boolean areSubnetsAdjacent(SubnetData subnet1, SubnetData subnet2) { 602 String broadcast1 = getBroadcastAddress(subnet1.getNetworkIP(), subnet1.getCidr()); 603 long broadcast1Long = ipToLong(broadcast1); 604 return subnet2.getNetworkLong() == broadcast1Long + 1; 605 } 606 607 /** 608 * 检查两个子网是否连续 609 */ 610 private boolean areSubnetsContiguous(SubnetData subnet1, SubnetData subnet2) { 611 String broadcast1 = getBroadcastAddress(subnet1.getNetworkIP(), subnet1.getCidr()); 612 long broadcast1Long = ipToLong(broadcast1); 613 return subnet2.getNetworkLong() <= broadcast1Long + 1; 614 } 615 616 /** 617 * 合并子网组 618 */ 619 private MergedSubnet mergeSubnetGroup(List<SubnetData> subnetGroup) { 620 SubnetData first = subnetGroup.get(0); 621 SubnetData last = subnetGroup.get(subnetGroup.size() - 1); 622 String lastBroadcast = getBroadcastAddress(last.getNetworkIP(), last.getCidr()); 623 long lastBroadcastLong = ipToLong(lastBroadcast); 624 625 // 计算合并后的CIDR 626 long rangeSize = lastBroadcastLong - first.getNetworkLong() + 1; 627 int mergedCIDR = 32 - (int) Math.ceil(Math.log(rangeSize) / Math.log(2)); 628 629 String mergedNetworkIP = longToIP(first.getNetworkLong()); 630 String mergedNetwork = mergedNetworkIP + "/" + mergedCIDR; 631 int mergedHostCount = getUsableHosts(mergedCIDR); 632 633 List<String> originalSubnets = new ArrayList<>(); 634 for (SubnetData subnet : subnetGroup) { 635 originalSubnets.add(subnet.getNetwork()); 636 } 637 638 return new MergedSubnet(mergedNetwork, originalSubnets, mergedHostCount); 639 } 640 641 /** 642 * 超网计算 643 */ 644 public SupernetResult calculateSupernet(String startIP, String endIP, Map<String, Object> options) 645 throws IllegalArgumentException { 646 if (!validateIP(startIP) || !validateIP(endIP)) { 647 throw new IllegalArgumentException("无效的IP地址格式"); 648 } 649 650 long startLong = ipToLong(startIP); 651 long endLong = ipToLong(endIP); 652 653 if (startLong > endLong) { 654 throw new IllegalArgumentException("起始IP不能大于结束IP"); 655 } 656 657 // 计算包含该范围的最小超网 658 long rangeSize = endLong - startLong + 1; 659 int requiredCIDR = 32 - (int) Math.ceil(Math.log(rangeSize) / Math.log(2)); 660 661 // 找到包含该范围的最小网络地址 662 long mask = (0xFFFFFFFFL << (32 - requiredCIDR)) & 0xFFFFFFFFL; 663 long networkLong = startLong & mask; 664 String networkIP = longToIP(networkLong); 665 666 // 验证该网络是否包含整个范围 667 long broadcastLong = networkLong | (~mask & 0xFFFFFFFFL); 668 if (broadcastLong < endLong) { 669 // 需要更大的网络 670 int newCIDR = requiredCIDR - 1; 671 long newMask = (0xFFFFFFFFL << (32 - newCIDR)) & 0xFFFFFFFFL; 672 long newNetworkLong = startLong & newMask; 673 String newNetworkIP = longToIP(newNetworkLong); 674 675 return new SupernetResult( 676 newNetworkIP, 677 getSubnetMask(newCIDR), 678 newCIDR, 679 longToIP(newNetworkLong | (~newMask & 0xFFFFFFFFL)), 680 longToIP(newNetworkLong + 1), 681 longToIP((newNetworkLong | (~newMask & 0xFFFFFFFFL)) - 1), 682 getUsableHosts(newCIDR), 683 startIP, 684 endIP, 685 String.format("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, newNetworkIP, newCIDR) 686 ); 687 } 688 689 return new SupernetResult( 690 networkIP, 691 getSubnetMask(requiredCIDR), 692 requiredCIDR, 693 longToIP(broadcastLong), 694 longToIP(networkLong + 1), 695 longToIP(broadcastLong - 1), 696 getUsableHosts(requiredCIDR), 697 startIP, 698 endIP, 699 String.format("计算得到包含范围 %s-%s 的最小超网 %s/%d", startIP, endIP, networkIP, requiredCIDR) 700 ); 701 } 702 703 /** 704 * 网络规划 705 */ 706 public PlanningResult generateNetworkPlan(String addressSpace, List<DepartmentRequirement> departmentRequirements, 707 Map<String, Object> options) throws IllegalArgumentException { 708 String[] parsed = parseCIDR(addressSpace); 709 String networkIP = parsed[0]; 710 int networkCIDRBits = Integer.parseInt(parsed[1]); 711 712 String networkAddress = getNetworkAddress(networkIP, networkCIDRBits); 713 long networkLong = ipToLong(networkAddress); 714 int totalSpace = getUsableHosts(networkCIDRBits); 715 716 // 按部门大小排序 717 List<DepartmentRequirement> sortedDepartments = new ArrayList<>(departmentRequirements); 718 if (options != null && options.containsKey("optimize_utilization") && 719 (Boolean) options.get("optimize_utilization")) { 720 sortedDepartments.sort((a, b) -> Integer.compare(b.getSize(), a.getSize())); 721 } 722 723 List<DepartmentInfo> departments = new ArrayList<>(); 724 long currentNetworkLong = networkLong; 725 int allocatedSpace = 0; 726 727 for (DepartmentRequirement dept : sortedDepartments) { 728 int requiredHosts = dept.getSize(); 729 if (options != null && options.containsKey("reserve_space") && 730 (Boolean) options.get("reserve_space")) { 731 requiredHosts += (int) Math.ceil(dept.getSize() * 0.2); 732 } 733 734 int requiredCIDR = 32 - (int) Math.ceil(Math.log(requiredHosts + 2) / Math.log(2)); // +2 for network and broadcast 735 736 if (requiredCIDR < networkCIDRBits) { 737 throw new IllegalArgumentException("部门 " + dept.getName() + " 需要的主机数超出可用空间"); 738 } 739 740 String deptNetworkIP = longToIP(currentNetworkLong); 741 String deptSubnetMask = getSubnetMask(requiredCIDR); 742 int deptHosts = getUsableHosts(requiredCIDR); 743 744 String firstHost = getFirstHost(deptNetworkIP, requiredCIDR); 745 String lastHost = getLastHost(deptNetworkIP, requiredCIDR); 746 747 departments.add(new DepartmentInfo( 748 dept.getName(), 749 deptNetworkIP, 750 deptSubnetMask, 751 requiredCIDR, 752 firstHost, 753 lastHost, 754 dept.getSize(), 755 deptHosts 756 )); 757 758 allocatedSpace += deptHosts; 759 long subnetSize = (long) Math.pow(2, 32 - requiredCIDR); 760 currentNetworkLong += subnetSize; 761 } 762 763 int remainingSpace = totalSpace - allocatedSpace; 764 double utilization = (double) allocatedSpace / totalSpace * 100; 765 766 return new PlanningResult( 767 departments, 768 new PlanningSummary(totalSpace, allocatedSpace, remainingSpace, utilization, departments.size()), 769 String.format("网络规划完成,共分配 %d 个部门,地址利用率 %.2f%%,剩余空间 %d 个主机", 770 departments.size(), utilization, remainingSpace) 771 ); 772 } 773 774 public static void main(String[] args) { 775 SubnetCalculator calculator = new SubnetCalculator(); 776 777 System.out.println("=== 子网划分工具 - Java版本 ==="); 778 779 // VLSM示例 780 System.out.println("\n--- VLSM子网划分示例 ---"); 781 try { 782 List<SubnetRequirement> requirements = Arrays.asList( 783 new SubnetRequirement("销售部", 50), 784 new SubnetRequirement("技术部", 30), 785 new SubnetRequirement("财务部", 10), 786 new SubnetRequirement("人事部", 5) 787 ); 788 789 Map<String, Object> options = new HashMap<>(); 790 options.put("optimize_order", true); 791 options.put("include_network_broadcast", true); 792 793 VLSMResult vlsmResult = calculator.calculateVLSM("192.168.1.0/24", requirements, options); 794 System.out.println("VLSM结果:"); 795 for (SubnetInfo subnet : vlsmResult.getSubnets()) { 796 System.out.printf(" %s: %s/%d (%s - %s)%n", 797 subnet.getName(), subnet.getNetworkAddress(), subnet.getCidr(), 798 subnet.getFirstHost(), subnet.getLastHost()); 799 } 800 System.out.printf("汇总: 原始网络=%s, 总子网数=%d, 总主机数=%d, 利用率=%.2f%%%n", 801 vlsmResult.getSummary().getOriginalNetwork(), 802 vlsmResult.getSummary().getTotalSubnets(), 803 vlsmResult.getSummary().getTotalHosts(), 804 vlsmResult.getSummary().getUtilization()); 805 } catch (Exception e) { 806 System.err.println("VLSM错误: " + e.getMessage()); 807 } 808 809 // 子网合并示例 810 System.out.println("\n--- 子网合并示例 ---"); 811 try { 812 List<String> subnetList = Arrays.asList( 813 "192.168.1.0/26", 814 "192.168.1.64/26", 815 "192.168.1.128/26", 816 "192.168.1.192/26" 817 ); 818 819 Map<String, Object> options = new HashMap<>(); 820 options.put("merge_adjacent", true); 821 options.put("merge_contiguous", true); 822 options.put("validate_subnets", true); 823 824 MergeResult mergeResult = calculator.mergeSubnets(subnetList, options); 825 System.out.println("合并结果:"); 826 for (MergedSubnet merged : mergeResult.getMergedSubnets()) { 827 System.out.printf(" %s (包含: %s)%n", merged.getNetwork(), 828 String.join(", ", merged.getOriginalSubnets())); 829 } 830 System.out.printf("汇总: 原子网数=%d, 合并后=%d, 减少=%d, 利用率=%.4f%%%n", 831 mergeResult.getSummary().getOriginalCount(), 832 mergeResult.getSummary().getMergedCount(), 833 mergeResult.getSummary().getReduction(), 834 mergeResult.getSummary().getUtilization()); 835 } catch (Exception e) { 836 System.err.println("合并错误: " + e.getMessage()); 837 } 838 839 // 超网计算示例 840 System.out.println("\n--- 超网计算示例 ---"); 841 try { 842 SupernetResult supernetResult = calculator.calculateSupernet("192.168.1.10", "192.168.1.50", null); 843 System.out.printf("超网结果: %s/%d%n", supernetResult.getNetworkAddress(), supernetResult.getCidr()); 844 System.out.printf("详细信息: %s%n", supernetResult.getDetails()); 845 } catch (Exception e) { 846 System.err.println("超网错误: " + e.getMessage()); 847 } 848 849 // 网络规划示例 850 System.out.println("\n--- 网络规划示例 ---"); 851 try { 852 List<DepartmentRequirement> deptRequirements = Arrays.asList( 853 new DepartmentRequirement("总部", 200), 854 new DepartmentRequirement("分公司A", 100), 855 new DepartmentRequirement("分公司B", 80), 856 new DepartmentRequirement("研发中心", 150) 857 ); 858 859 Map<String, Object> options = new HashMap<>(); 860 options.put("optimize_utilization", true); 861 options.put("reserve_space", true); 862 863 PlanningResult planningResult = calculator.generateNetworkPlan("10.0.0.0/8", deptRequirements, options); 864 System.out.println("规划结果:"); 865 for (DepartmentInfo dept : planningResult.getDepartments()) { 866 System.out.printf(" %s: %s/%d (%d 主机)%n", dept.getName(), 867 dept.getNetworkAddress(), dept.getCidr(), dept.getAllocatedHosts()); 868 } 869 System.out.printf("汇总: 总空间=%d, 已分配=%d, 剩余=%d, 利用率=%.2f%%, 部门数=%d%n", 870 planningResult.getSummary().getTotalSpace(), 871 planningResult.getSummary().getAllocatedSpace(), 872 planningResult.getSummary().getRemainingSpace(), 873 planningResult.getSummary().getUtilization(), 874 planningResult.getSummary().getDepartmentCount()); 875 } catch (Exception e) { 876 System.err.println("规划错误: " + e.getMessage()); 877 } 878 } 879}
-
subnet_calculator (JS)
1/** 2 * 子网划分工具 - JavaScript版本 3 * 支持VLSM可变长子网掩码、子网合并、超网计算、网络规划等功能 4 */ 5class SubnetCalculator { 6 constructor() { 7 this.ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; 8 this.cidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$/; 9 } 10 11 /** 12 * 验证IP地址格式 13 */ 14 validateIP(ip) { 15 return this.ipRegex.test(ip); 16 } 17 18 /** 19 * 验证CIDR格式 20 */ 21 validateCIDR(cidr) { 22 return this.cidrRegex.test(cidr); 23 } 24 25 /** 26 * IP地址转换为整数 27 */ 28 ipToInt(ip) { 29 if (!this.validateIP(ip)) { 30 throw new Error('无效的IP地址格式'); 31 } 32 33 const parts = ip.split('.').map(Number); 34 return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]; 35 } 36 37 /** 38 * 整数转换为IP地址 39 */ 40 intToIP(int) { 41 return [ 42 (int >>> 24) & 255, 43 (int >>> 16) & 255, 44 (int >>> 8) & 255, 45 int & 255 46 ].join('.'); 47 } 48 49 /** 50 * 获取子网掩码 51 */ 52 getSubnetMask(cidr) { 53 const mask = (0xFFFFFFFF << (32 - cidr)) >>> 0; 54 return this.intToIP(mask); 55 } 56 57 /** 58 * 获取网络地址 59 */ 60 getNetworkAddress(ip, cidr) { 61 const ipInt = this.ipToInt(ip); 62 const mask = (0xFFFFFFFF << (32 - cidr)) >>> 0; 63 const networkInt = ipInt & mask; 64 return this.intToIP(networkInt); 65 } 66 67 /** 68 * 获取广播地址 69 */ 70 getBroadcastAddress(ip, cidr) { 71 const ipInt = this.ipToInt(ip); 72 const mask = (0xFFFFFFFF << (32 - cidr)) >>> 0; 73 const broadcastInt = ipInt | (~mask >>> 0); 74 return this.intToIP(broadcastInt); 75 } 76 77 /** 78 * 获取第一个可用主机地址 79 */ 80 getFirstHost(ip, cidr) { 81 const networkInt = this.ipToInt(this.getNetworkAddress(ip, cidr)); 82 return this.intToIP(networkInt + 1); 83 } 84 85 /** 86 * 获取最后一个可用主机地址 87 */ 88 getLastHost(ip, cidr) { 89 const broadcastInt = this.ipToInt(this.getBroadcastAddress(ip, cidr)); 90 return this.intToIP(broadcastInt - 1); 91 } 92 93 /** 94 * 计算可用主机数量 95 */ 96 getUsableHosts(cidr) { 97 return Math.pow(2, 32 - cidr) - 2; 98 } 99 100 /** 101 * 解析CIDR格式 102 */ 103 parseCIDR(cidr) { 104 if (!this.validateCIDR(cidr)) { 105 throw new Error('无效的CIDR格式'); 106 } 107 108 const [ip, maskBits] = cidr.split('/'); 109 return { 110 ip: ip, 111 cidr: parseInt(maskBits), 112 subnetMask: this.getSubnetMask(parseInt(maskBits)) 113 }; 114 } 115 116 /** 117 * VLSM子网划分 118 */ 119 calculateVLSM(networkCIDR, subnetRequirements, options = {}) { 120 const { ip: networkIP, cidr: networkCIDR } = this.parseCIDR(networkCIDR); 121 const networkInt = this.ipToInt(this.getNetworkAddress(networkIP, networkCIDR)); 122 const totalHosts = this.getUsableHosts(networkCIDR); 123 124 // 按主机数量排序(如果需要) 125 let sortedRequirements = [...subnetRequirements]; 126 if (options.optimizeOrder) { 127 sortedRequirements.sort((a, b) => b.hosts - a.hosts); 128 } 129 130 // 计算每个子网需要的掩码位数 131 const subnets = []; 132 let currentNetworkInt = networkInt; 133 134 for (const requirement of sortedRequirements) { 135 const requiredHosts = requirement.hosts + (options.includeNetworkBroadcast ? 2 : 0); 136 const requiredCIDR = 32 - Math.ceil(Math.log2(requiredHosts)); 137 138 if (requiredCIDR < networkCIDR) { 139 throw new Error(`子网 ${requirement.name} 需要的主机数超出可用空间`); 140 } 141 142 const subnetNetworkIP = this.intToIP(currentNetworkInt); 143 const subnetMask = this.getSubnetMask(requiredCIDR); 144 const subnetHosts = this.getUsableHosts(requiredCIDR); 145 146 subnets.push({ 147 name: requirement.name, 148 networkAddress: subnetNetworkIP, 149 subnetMask: subnetMask, 150 cidr: requiredCIDR, 151 firstHost: this.getFirstHost(subnetNetworkIP, requiredCIDR), 152 lastHost: this.getLastHost(subnetNetworkIP, requiredCIDR), 153 broadcastAddress: this.getBroadcastAddress(subnetNetworkIP, requiredCIDR), 154 usableHosts: subnetHosts, 155 requiredHosts: requirement.hosts 156 }); 157 158 // 计算下一个子网的起始地址 159 const subnetSize = Math.pow(2, 32 - requiredCIDR); 160 currentNetworkInt += subnetSize; 161 } 162 163 // 计算汇总信息 164 const totalRequiredHosts = sortedRequirements.reduce((sum, req) => sum + req.hosts, 0); 165 const utilization = ((totalRequiredHosts / totalHosts) * 100).toFixed(2); 166 167 return { 168 subnets: subnets, 169 summary: { 170 originalNetwork: networkCIDR, 171 totalSubnets: subnets.length, 172 totalHosts: totalRequiredHosts, 173 utilization: utilization 174 }, 175 details: `VLSM划分完成,共创建 ${subnets.length} 个子网,地址利用率 ${utilization}%` 176 }; 177 } 178 179 /** 180 * 子网合并 181 */ 182 mergeSubnets(subnetList, options = {}) { 183 const subnets = []; 184 185 // 解析子网列表 186 for (const subnetStr of subnetList) { 187 if (!this.validateCIDR(subnetStr)) { 188 if (options.validateSubnets) { 189 throw new Error(`无效的子网格式: ${subnetStr}`); 190 } 191 continue; 192 } 193 194 const { ip, cidr } = this.parseCIDR(subnetStr); 195 const networkIP = this.getNetworkAddress(ip, cidr); 196 subnets.push({ 197 network: subnetStr, 198 networkIP: networkIP, 199 cidr: cidr, 200 networkInt: this.ipToInt(networkIP), 201 hostCount: this.getUsableHosts(cidr) 202 }); 203 } 204 205 if (subnets.length === 0) { 206 throw new Error('没有有效的子网可以合并'); 207 } 208 209 // 按网络地址排序 210 subnets.sort((a, b) => a.networkInt - b.networkInt); 211 212 const mergedSubnets = []; 213 let currentGroup = [subnets[0]]; 214 215 for (let i = 1; i < subnets.length; i++) { 216 const current = subnets[i]; 217 const last = currentGroup[currentGroup.length - 1]; 218 219 // 检查是否相邻或连续 220 const isAdjacent = options.mergeAdjacent && 221 this.areSubnetsAdjacent(last, current); 222 const isContiguous = options.mergeContiguous && 223 this.areSubnetsContiguous(last, current); 224 225 if (isAdjacent || isContiguous) { 226 currentGroup.push(current); 227 } else { 228 // 合并当前组 229 if (currentGroup.length > 1) { 230 mergedSubnets.push(this.mergeSubnetGroup(currentGroup)); 231 } else { 232 mergedSubnets.push({ 233 network: currentGroup[0].network, 234 originalSubnets: [currentGroup[0].network], 235 hostCount: currentGroup[0].hostCount 236 }); 237 } 238 currentGroup = [current]; 239 } 240 } 241 242 // 处理最后一组 243 if (currentGroup.length > 1) { 244 mergedSubnets.push(this.mergeSubnetGroup(currentGroup)); 245 } else { 246 mergedSubnets.push({ 247 network: currentGroup[0].network, 248 originalSubnets: [currentGroup[0].network], 249 hostCount: currentGroup[0].hostCount 250 }); 251 } 252 253 // 计算汇总信息 254 const originalCount = subnets.length; 255 const mergedCount = mergedSubnets.length; 256 const reduction = originalCount - mergedCount; 257 const totalHosts = mergedSubnets.reduce((sum, subnet) => sum + subnet.hostCount, 0); 258 259 return { 260 mergedSubnets: mergedSubnets, 261 summary: { 262 originalCount: originalCount, 263 mergedCount: mergedCount, 264 reduction: reduction, 265 totalHosts: totalHosts, 266 utilization: ((totalHosts / (Math.pow(2, 32) - 1)) * 100).toFixed(4) 267 }, 268 details: `合并完成,从 ${originalCount} 个子网合并为 ${mergedCount} 个,减少 ${reduction} 个` 269 }; 270 } 271 272 /** 273 * 检查两个子网是否相邻 274 */ 275 areSubnetsAdjacent(subnet1, subnet2) { 276 const broadcast1 = this.ipToInt(this.getBroadcastAddress(subnet1.networkIP, subnet1.cidr)); 277 const network2 = subnet2.networkInt; 278 return network2 === broadcast1 + 1; 279 } 280 281 /** 282 * 检查两个子网是否连续 283 */ 284 areSubnetsContiguous(subnet1, subnet2) { 285 const broadcast1 = this.ipToInt(this.getBroadcastAddress(subnet1.networkIP, subnet1.cidr)); 286 const network2 = subnet2.networkInt; 287 return network2 <= broadcast1 + 1; 288 } 289 290 /** 291 * 合并子网组 292 */ 293 mergeSubnetGroup(subnetGroup) { 294 const first = subnetGroup[0]; 295 const last = subnetGroup[subnetGroup.length - 1]; 296 const lastBroadcast = this.ipToInt(this.getBroadcastAddress(last.networkIP, last.cidr)); 297 298 // 计算合并后的CIDR 299 const range = lastBroadcast - first.networkInt + 1; 300 const mergedCIDR = 32 - Math.ceil(Math.log2(range)); 301 302 const mergedNetworkIP = this.intToIP(first.networkInt); 303 const mergedNetwork = `${mergedNetworkIP}/${mergedCIDR}`; 304 const mergedHostCount = this.getUsableHosts(mergedCIDR); 305 306 return { 307 network: mergedNetwork, 308 originalSubnets: subnetGroup.map(s => s.network), 309 hostCount: mergedHostCount 310 }; 311 } 312 313 /** 314 * 超网计算 315 */ 316 calculateSupernet(startIP, endIP, options = {}) { 317 if (!this.validateIP(startIP) || !this.validateIP(endIP)) { 318 throw new Error('无效的IP地址格式'); 319 } 320 321 const startInt = this.ipToInt(startIP); 322 const endInt = this.ipToInt(endIP); 323 324 if (startInt > endInt) { 325 throw new Error('起始IP不能大于结束IP'); 326 } 327 328 // 计算包含该范围的最小超网 329 const range = endInt - startInt + 1; 330 const requiredCIDR = 32 - Math.ceil(Math.log2(range)); 331 332 // 找到包含该范围的最小网络地址 333 const mask = (0xFFFFFFFF << (32 - requiredCIDR)) >>> 0; 334 const networkInt = startInt & mask; 335 const networkIP = this.intToIP(networkInt); 336 337 // 验证该网络是否包含整个范围 338 const broadcastInt = networkInt | (~mask >>> 0); 339 if (broadcastInt < endInt) { 340 // 需要更大的网络 341 const newCIDR = requiredCIDR - 1; 342 const newMask = (0xFFFFFFFF << (32 - newCIDR)) >>> 0; 343 const newNetworkInt = startInt & newMask; 344 const newNetworkIP = this.intToIP(newNetworkInt); 345 346 return { 347 networkAddress: newNetworkIP, 348 subnetMask: this.getSubnetMask(newCIDR), 349 cidr: newCIDR, 350 networkAddress: newNetworkIP, 351 broadcastAddress: this.intToIP(newNetworkInt | (~newMask >>> 0)), 352 firstHost: this.intToIP(newNetworkInt + 1), 353 lastHost: this.intToIP((newNetworkInt | (~newMask >>> 0)) - 1), 354 totalHosts: this.getUsableHosts(newCIDR), 355 startIP: startIP, 356 endIP: endIP, 357 details: `计算得到包含范围 ${startIP}-${endIP} 的最小超网 ${newNetworkIP}/${newCIDR}` 358 }; 359 } 360 361 return { 362 networkAddress: networkIP, 363 subnetMask: this.getSubnetMask(requiredCIDR), 364 cidr: requiredCIDR, 365 networkAddress: networkIP, 366 broadcastAddress: this.intToIP(broadcastInt), 367 firstHost: this.intToIP(networkInt + 1), 368 lastHost: this.intToIP(broadcastInt - 1), 369 totalHosts: this.getUsableHosts(requiredCIDR), 370 startIP: startIP, 371 endIP: endIP, 372 details: `计算得到包含范围 ${startIP}-${endIP} 的最小超网 ${networkIP}/${requiredCIDR}` 373 }; 374 } 375 376 /** 377 * 网络规划 378 */ 379 generateNetworkPlan(addressSpace, departmentRequirements, options = {}) { 380 const { ip: networkIP, cidr: networkCIDR } = this.parseCIDR(addressSpace); 381 const networkInt = this.ipToInt(this.getNetworkAddress(networkIP, networkCIDR)); 382 const totalSpace = this.getUsableHosts(networkCIDR); 383 384 // 按部门大小排序 385 let sortedDepartments = [...departmentRequirements]; 386 if (options.optimizeUtilization) { 387 sortedDepartments.sort((a, b) => b.size - a.size); 388 } 389 390 const departments = []; 391 let currentNetworkInt = networkInt; 392 let allocatedSpace = 0; 393 394 for (const dept of sortedDepartments) { 395 const requiredHosts = dept.size + (options.reserveSpace ? Math.ceil(dept.size * 0.2) : 0); 396 const requiredCIDR = 32 - Math.ceil(Math.log2(requiredHosts + 2)); // +2 for network and broadcast 397 398 if (requiredCIDR < networkCIDR) { 399 throw new Error(`部门 ${dept.name} 需要的主机数超出可用空间`); 400 } 401 402 const deptNetworkIP = this.intToIP(currentNetworkInt); 403 const deptSubnetMask = this.getSubnetMask(requiredCIDR); 404 const deptHosts = this.getUsableHosts(requiredCIDR); 405 406 departments.push({ 407 name: dept.name, 408 networkAddress: deptNetworkIP, 409 subnetMask: deptSubnetMask, 410 cidr: requiredCIDR, 411 firstHost: this.getFirstHost(deptNetworkIP, requiredCIDR), 412 lastHost: this.getLastHost(deptNetworkIP, requiredCIDR), 413 allocatedHosts: dept.size, 414 totalHosts: deptHosts 415 }); 416 417 allocatedSpace += deptHosts; 418 const subnetSize = Math.pow(2, 32 - requiredCIDR); 419 currentNetworkInt += subnetSize; 420 } 421 422 const remainingSpace = totalSpace - allocatedSpace; 423 const utilization = ((allocatedSpace / totalSpace) * 100).toFixed(2); 424 425 return { 426 departments: departments, 427 summary: { 428 totalSpace: totalSpace, 429 allocatedSpace: allocatedSpace, 430 remainingSpace: remainingSpace, 431 utilization: utilization, 432 departmentCount: departments.length 433 }, 434 details: `网络规划完成,共分配 ${departments.length} 个部门,地址利用率 ${utilization}%,剩余空间 ${remainingSpace} 个主机` 435 }; 436 } 437} 438 439// 使用示例 440const calculator = new SubnetCalculator(); 441 442// VLSM示例 443console.log('=== VLSM子网划分示例 ==='); 444try { 445 const vlsmResult = calculator.calculateVLSM('192.168.1.0/24', [ 446 { name: '销售部', hosts: 50 }, 447 { name: '技术部', hosts: 30 }, 448 { name: '财务部', hosts: 10 }, 449 { name: '人事部', hosts: 5 } 450 ]); 451 console.log('VLSM结果:', JSON.stringify(vlsmResult, null, 2)); 452} catch (error) { 453 console.error('VLSM错误:', error.message); 454} 455 456// 子网合并示例 457console.log('\n=== 子网合并示例 ==='); 458try { 459 const mergeResult = calculator.mergeSubnets([ 460 '192.168.1.0/26', 461 '192.168.1.64/26', 462 '192.168.1.128/26', 463 '192.168.1.192/26' 464 ]); 465 console.log('合并结果:', JSON.stringify(mergeResult, null, 2)); 466} catch (error) { 467 console.error('合并错误:', error.message); 468} 469 470// 超网计算示例 471console.log('\n=== 超网计算示例 ==='); 472try { 473 const supernetResult = calculator.calculateSupernet('192.168.1.10', '192.168.1.50'); 474 console.log('超网结果:', JSON.stringify(supernetResult, null, 2)); 475} catch (error) { 476 console.error('超网错误:', error.message); 477} 478 479// 网络规划示例 480console.log('\n=== 网络规划示例 ==='); 481try { 482 const planningResult = calculator.generateNetworkPlan('10.0.0.0/8', [ 483 { name: '总部', size: 200 }, 484 { name: '分公司A', size: 100 }, 485 { name: '分公司B', size: 80 }, 486 { name: '研发中心', size: 150 } 487 ]); 488 console.log('规划结果:', JSON.stringify(planningResult, null, 2)); 489} catch (error) { 490 console.error('规划错误:', error.message); 491}
-
subnet_calculator (PHP)
1<?php 2/** 3 * 子网划分工具 - PHP版本 4 * 支持VLSM可变长子网掩码、子网合并、超网计算、网络规划等功能 5 */ 6class SubnetCalculator { 7 private $ipRegex; 8 private $cidrRegex; 9 10 public function __construct() { 11 $this->ipRegex = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; 12 $this->cidrRegex = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$/'; 13 } 14 15 /** 16 * 验证IP地址格式 17 */ 18 public function validateIP($ip) { 19 return preg_match($this->ipRegex, $ip); 20 } 21 22 /** 23 * 验证CIDR格式 24 */ 25 public function validateCIDR($cidr) { 26 return preg_match($this->cidrRegex, $cidr); 27 } 28 29 /** 30 * IP地址转换为整数 31 */ 32 public function ipToInt($ip) { 33 if (!$this->validateIP($ip)) { 34 throw new Exception('无效的IP地址格式'); 35 } 36 37 $parts = explode('.', $ip); 38 return ($parts[0] << 24) + ($parts[1] << 16) + ($parts[2] << 8) + $parts[3]; 39 } 40 41 /** 42 * 整数转换为IP地址 43 */ 44 public function intToIP($ipInt) { 45 return sprintf('%d.%d.%d.%d', 46 ($ipInt >> 24) & 255, 47 ($ipInt >> 16) & 255, 48 ($ipInt >> 8) & 255, 49 $ipInt & 255 50 ); 51 } 52 53 /** 54 * 获取子网掩码 55 */ 56 public function getSubnetMask($cidr) { 57 $mask = (0xFFFFFFFF << (32 - $cidr)) & 0xFFFFFFFF; 58 return $this->intToIP($mask); 59 } 60 61 /** 62 * 获取网络地址 63 */ 64 public function getNetworkAddress($ip, $cidr) { 65 $ipInt = $this->ipToInt($ip); 66 $mask = (0xFFFFFFFF << (32 - $cidr)) & 0xFFFFFFFF; 67 $networkInt = $ipInt & $mask; 68 return $this->intToIP($networkInt); 69 } 70 71 /** 72 * 获取广播地址 73 */ 74 public function getBroadcastAddress($ip, $cidr) { 75 $ipInt = $this->ipToInt($ip); 76 $mask = (0xFFFFFFFF << (32 - $cidr)) & 0xFFFFFFFF; 77 $broadcastInt = $ipInt | (~$mask & 0xFFFFFFFF); 78 return $this->intToIP($broadcastInt); 79 } 80 81 /** 82 * 获取第一个可用主机地址 83 */ 84 public function getFirstHost($ip, $cidr) { 85 $networkIP = $this->getNetworkAddress($ip, $cidr); 86 $networkInt = $this->ipToInt($networkIP); 87 return $this->intToIP($networkInt + 1); 88 } 89 90 /** 91 * 获取最后一个可用主机地址 92 */ 93 public function getLastHost($ip, $cidr) { 94 $broadcastIP = $this->getBroadcastAddress($ip, $cidr); 95 $broadcastInt = $this->ipToInt($broadcastIP); 96 return $this->intToIP($broadcastInt - 1); 97 } 98 99 /** 100 * 计算可用主机数量 101 */ 102 public function getUsableHosts($cidr) { 103 return pow(2, 32 - $cidr) - 2; 104 } 105 106 /** 107 * 解析CIDR格式 108 */ 109 public function parseCIDR($cidr) { 110 if (!$this->validateCIDR($cidr)) { 111 throw new Exception('无效的CIDR格式'); 112 } 113 114 $parts = explode('/', $cidr); 115 return [ 116 'ip' => $parts[0], 117 'cidr' => (int)$parts[1], 118 'subnet_mask' => $this->getSubnetMask((int)$parts[1]) 119 ]; 120 } 121 122 /** 123 * VLSM子网划分 124 */ 125 public function calculateVLSM($networkCIDR, $subnetRequirements, $options = []) { 126 $parsed = $this->parseCIDR($networkCIDR); 127 $networkIP = $parsed['ip']; 128 $networkCIDRBits = $parsed['cidr']; 129 130 $networkAddress = $this->getNetworkAddress($networkIP, $networkCIDRBits); 131 $networkInt = $this->ipToInt($networkAddress); 132 $totalHosts = $this->getUsableHosts($networkCIDRBits); 133 134 // 按主机数量排序(如果需要) 135 $sortedRequirements = $subnetRequirements; 136 if (isset($options['optimize_order']) && $options['optimize_order']) { 137 usort($sortedRequirements, function($a, $b) { 138 return $b['hosts'] - $a['hosts']; 139 }); 140 } 141 142 // 计算每个子网需要的掩码位数 143 $subnets = []; 144 $currentNetworkInt = $networkInt; 145 146 foreach ($sortedRequirements as $requirement) { 147 $requiredHosts = $requirement['hosts']; 148 if (isset($options['include_network_broadcast']) && $options['include_network_broadcast']) { 149 $requiredHosts += 2; 150 } 151 152 $requiredCIDR = 32 - ceil(log($requiredHosts, 2)); 153 154 if ($requiredCIDR < $networkCIDRBits) { 155 throw new Exception("子网 {$requirement['name']} 需要的主机数超出可用空间"); 156 } 157 158 $subnetNetworkIP = $this->intToIP($currentNetworkInt); 159 $subnetMask = $this->getSubnetMask($requiredCIDR); 160 $subnetHosts = $this->getUsableHosts($requiredCIDR); 161 162 $firstHost = $this->getFirstHost($subnetNetworkIP, $requiredCIDR); 163 $lastHost = $this->getLastHost($subnetNetworkIP, $requiredCIDR); 164 $broadcastAddress = $this->getBroadcastAddress($subnetNetworkIP, $requiredCIDR); 165 166 $subnets[] = [ 167 'name' => $requirement['name'], 168 'network_address' => $subnetNetworkIP, 169 'subnet_mask' => $subnetMask, 170 'cidr' => $requiredCIDR, 171 'first_host' => $firstHost, 172 'last_host' => $lastHost, 173 'broadcast_address' => $broadcastAddress, 174 'usable_hosts' => $subnetHosts, 175 'required_hosts' => $requirement['hosts'] 176 ]; 177 178 // 计算下一个子网的起始地址 179 $subnetSize = pow(2, 32 - $requiredCIDR); 180 $currentNetworkInt += $subnetSize; 181 } 182 183 // 计算汇总信息 184 $totalRequiredHosts = array_sum(array_column($sortedRequirements, 'hosts')); 185 $utilization = round(($totalRequiredHosts / $totalHosts) * 100, 2); 186 187 return [ 188 'subnets' => $subnets, 189 'summary' => [ 190 'original_network' => $networkCIDR, 191 'total_subnets' => count($subnets), 192 'total_hosts' => $totalRequiredHosts, 193 'utilization' => $utilization 194 ], 195 'details' => "VLSM划分完成,共创建 " . count($subnets) . " 个子网,地址利用率 {$utilization}%" 196 ]; 197 } 198 199 /** 200 * 子网合并 201 */ 202 public function mergeSubnets($subnetList, $options = []) { 203 $subnets = []; 204 205 // 解析子网列表 206 foreach ($subnetList as $subnetStr) { 207 if (!$this->validateCIDR($subnetStr)) { 208 if (isset($options['validate_subnets']) && $options['validate_subnets']) { 209 throw new Exception("无效的子网格式: {$subnetStr}"); 210 } 211 continue; 212 } 213 214 $parsed = $this->parseCIDR($subnetStr); 215 $networkIP = $this->getNetworkAddress($parsed['ip'], $parsed['cidr']); 216 $networkInt = $this->ipToInt($networkIP); 217 218 $subnets[] = [ 219 'network' => $subnetStr, 220 'network_ip' => $networkIP, 221 'cidr' => $parsed['cidr'], 222 'network_int' => $networkInt, 223 'host_count' => $this->getUsableHosts($parsed['cidr']) 224 ]; 225 } 226 227 if (empty($subnets)) { 228 throw new Exception('没有有效的子网可以合并'); 229 } 230 231 // 按网络地址排序 232 usort($subnets, function($a, $b) { 233 return $a['network_int'] - $b['network_int']; 234 }); 235 236 $mergedSubnets = []; 237 $currentGroup = [$subnets[0]]; 238 239 for ($i = 1; $i < count($subnets); $i++) { 240 $current = $subnets[$i]; 241 $last = $currentGroup[count($currentGroup) - 1]; 242 243 // 检查是否相邻或连续 244 $isAdjacent = false; 245 $isContiguous = false; 246 247 if (isset($options['merge_adjacent']) && $options['merge_adjacent']) { 248 $isAdjacent = $this->areSubnetsAdjacent($last, $current); 249 } 250 251 if (isset($options['merge_contiguous']) && $options['merge_contiguous']) { 252 $isContiguous = $this->areSubnetsContiguous($last, $current); 253 } 254 255 if ($isAdjacent || $isContiguous) { 256 $currentGroup[] = $current; 257 } else { 258 // 合并当前组 259 if (count($currentGroup) > 1) { 260 $mergedSubnets[] = $this->mergeSubnetGroup($currentGroup); 261 } else { 262 $mergedSubnets[] = [ 263 'network' => $currentGroup[0]['network'], 264 'original_subnets' => [$currentGroup[0]['network']], 265 'host_count' => $currentGroup[0]['host_count'] 266 ]; 267 } 268 $currentGroup = [$current]; 269 } 270 } 271 272 // 处理最后一组 273 if (count($currentGroup) > 1) { 274 $mergedSubnets[] = $this->mergeSubnetGroup($currentGroup); 275 } else { 276 $mergedSubnets[] = [ 277 'network' => $currentGroup[0]['network'], 278 'original_subnets' => [$currentGroup[0]['network']], 279 'host_count' => $currentGroup[0]['host_count'] 280 ]; 281 } 282 283 // 计算汇总信息 284 $originalCount = count($subnets); 285 $mergedCount = count($mergedSubnets); 286 $reduction = $originalCount - $mergedCount; 287 $totalHosts = array_sum(array_column($mergedSubnets, 'host_count')); 288 289 return [ 290 'merged_subnets' => $mergedSubnets, 291 'summary' => [ 292 'original_count' => $originalCount, 293 'merged_count' => $mergedCount, 294 'reduction' => $reduction, 295 'total_hosts' => $totalHosts, 296 'utilization' => round(($totalHosts / (pow(2, 32) - 1)) * 100, 4) 297 ], 298 'details' => "合并完成,从 {$originalCount} 个子网合并为 {$mergedCount} 个,减少 {$reduction} 个" 299 ]; 300 } 301 302 /** 303 * 检查两个子网是否相邻 304 */ 305 private function areSubnetsAdjacent($subnet1, $subnet2) { 306 $broadcast1 = $this->ipToInt($this->getBroadcastAddress($subnet1['network_ip'], $subnet1['cidr'])); 307 $network2 = $subnet2['network_int']; 308 return $network2 == $broadcast1 + 1; 309 } 310 311 /** 312 * 检查两个子网是否连续 313 */ 314 private function areSubnetsContiguous($subnet1, $subnet2) { 315 $broadcast1 = $this->ipToInt($this->getBroadcastAddress($subnet1['network_ip'], $subnet1['cidr'])); 316 $network2 = $subnet2['network_int']; 317 return $network2 <= $broadcast1 + 1; 318 } 319 320 /** 321 * 合并子网组 322 */ 323 private function mergeSubnetGroup($subnetGroup) { 324 $first = $subnetGroup[0]; 325 $last = $subnetGroup[count($subnetGroup) - 1]; 326 $lastBroadcast = $this->ipToInt($this->getBroadcastAddress($last['network_ip'], $last['cidr'])); 327 328 // 计算合并后的CIDR 329 $rangeSize = $lastBroadcast - $first['network_int'] + 1; 330 $mergedCIDR = 32 - ceil(log($rangeSize, 2)); 331 332 $mergedNetworkIP = $this->intToIP($first['network_int']); 333 $mergedNetwork = "{$mergedNetworkIP}/{$mergedCIDR}"; 334 $mergedHostCount = $this->getUsableHosts($mergedCIDR); 335 336 $originalSubnets = array_column($subnetGroup, 'network'); 337 338 return [ 339 'network' => $mergedNetwork, 340 'original_subnets' => $originalSubnets, 341 'host_count' => $mergedHostCount 342 ]; 343 } 344 345 /** 346 * 超网计算 347 */ 348 public function calculateSupernet($startIP, $endIP, $options = []) { 349 if (!$this->validateIP($startIP) || !$this->validateIP($endIP)) { 350 throw new Exception('无效的IP地址格式'); 351 } 352 353 $startInt = $this->ipToInt($startIP); 354 $endInt = $this->ipToInt($endIP); 355 356 if ($startInt > $endInt) { 357 throw new Exception('起始IP不能大于结束IP'); 358 } 359 360 // 计算包含该范围的最小超网 361 $rangeSize = $endInt - $startInt + 1; 362 $requiredCIDR = 32 - ceil(log($rangeSize, 2)); 363 364 // 找到包含该范围的最小网络地址 365 $mask = (0xFFFFFFFF << (32 - $requiredCIDR)) & 0xFFFFFFFF; 366 $networkInt = $startInt & $mask; 367 $networkIP = $this->intToIP($networkInt); 368 369 // 验证该网络是否包含整个范围 370 $broadcastInt = $networkInt | (~$mask & 0xFFFFFFFF); 371 if ($broadcastInt < $endInt) { 372 // 需要更大的网络 373 $newCIDR = $requiredCIDR - 1; 374 $newMask = (0xFFFFFFFF << (32 - $newCIDR)) & 0xFFFFFFFF; 375 $newNetworkInt = $startInt & $newMask; 376 $newNetworkIP = $this->intToIP($newNetworkInt); 377 378 return [ 379 'network_address' => $newNetworkIP, 380 'subnet_mask' => $this->getSubnetMask($newCIDR), 381 'cidr' => $newCIDR, 382 'broadcast_address' => $this->intToIP($newNetworkInt | (~$newMask & 0xFFFFFFFF)), 383 'first_host' => $this->intToIP($newNetworkInt + 1), 384 'last_host' => $this->intToIP(($newNetworkInt | (~$newMask & 0xFFFFFFFF)) - 1), 385 'total_hosts' => $this->getUsableHosts($newCIDR), 386 'start_ip' => $startIP, 387 'end_ip' => $endIP, 388 'details' => "计算得到包含范围 {$startIP}-{$endIP} 的最小超网 {$newNetworkIP}/{$newCIDR}" 389 ]; 390 } 391 392 return [ 393 'network_address' => $networkIP, 394 'subnet_mask' => $this->getSubnetMask($requiredCIDR), 395 'cidr' => $requiredCIDR, 396 'broadcast_address' => $this->intToIP($broadcastInt), 397 'first_host' => $this->intToIP($networkInt + 1), 398 'last_host' => $this->intToIP($broadcastInt - 1), 399 'total_hosts' => $this->getUsableHosts($requiredCIDR), 400 'start_ip' => $startIP, 401 'end_ip' => $endIP, 402 'details' => "计算得到包含范围 {$startIP}-{$endIP} 的最小超网 {$networkIP}/{$requiredCIDR}" 403 ]; 404 } 405 406 /** 407 * 网络规划 408 */ 409 public function generateNetworkPlan($addressSpace, $departmentRequirements, $options = []) { 410 $parsed = $this->parseCIDR($addressSpace); 411 $networkIP = $parsed['ip']; 412 $networkCIDRBits = $parsed['cidr']; 413 414 $networkAddress = $this->getNetworkAddress($networkIP, $networkCIDRBits); 415 $networkInt = $this->ipToInt($networkAddress); 416 $totalSpace = $this->getUsableHosts($networkCIDRBits); 417 418 // 按部门大小排序 419 $sortedDepartments = $departmentRequirements; 420 if (isset($options['optimize_utilization']) && $options['optimize_utilization']) { 421 usort($sortedDepartments, function($a, $b) { 422 return $b['size'] - $a['size']; 423 }); 424 } 425 426 $departments = []; 427 $currentNetworkInt = $networkInt; 428 $allocatedSpace = 0; 429 430 foreach ($sortedDepartments as $dept) { 431 $requiredHosts = $dept['size']; 432 if (isset($options['reserve_space']) && $options['reserve_space']) { 433 $requiredHosts += ceil($dept['size'] * 0.2); 434 } 435 436 $requiredCIDR = 32 - ceil(log($requiredHosts + 2, 2)); // +2 for network and broadcast 437 438 if ($requiredCIDR < $networkCIDRBits) { 439 throw new Exception("部门 {$dept['name']} 需要的主机数超出可用空间"); 440 } 441 442 $deptNetworkIP = $this->intToIP($currentNetworkInt); 443 $deptSubnetMask = $this->getSubnetMask($requiredCIDR); 444 $deptHosts = $this->getUsableHosts($requiredCIDR); 445 446 $firstHost = $this->getFirstHost($deptNetworkIP, $requiredCIDR); 447 $lastHost = $this->getLastHost($deptNetworkIP, $requiredCIDR); 448 449 $departments[] = [ 450 'name' => $dept['name'], 451 'network_address' => $deptNetworkIP, 452 'subnet_mask' => $deptSubnetMask, 453 'cidr' => $requiredCIDR, 454 'first_host' => $firstHost, 455 'last_host' => $lastHost, 456 'allocated_hosts' => $dept['size'], 457 'total_hosts' => $deptHosts 458 ]; 459 460 $allocatedSpace += $deptHosts; 461 $subnetSize = pow(2, 32 - $requiredCIDR); 462 $currentNetworkInt += $subnetSize; 463 } 464 465 $remainingSpace = $totalSpace - $allocatedSpace; 466 $utilization = round(($allocatedSpace / $totalSpace) * 100, 2); 467 468 return [ 469 'departments' => $departments, 470 'summary' => [ 471 'total_space' => $totalSpace, 472 'allocated_space' => $allocatedSpace, 473 'remaining_space' => $remainingSpace, 474 'utilization' => $utilization, 475 'department_count' => count($departments) 476 ], 477 'details' => "网络规划完成,共分配 " . count($departments) . " 个部门,地址利用率 {$utilization}%,剩余空间 {$remainingSpace} 个主机" 478 ]; 479 } 480 481 /** 482 * 获取子网详细信息(使用PHP内置函数) 483 */ 484 public function getSubnetInfo($ip, $cidr) { 485 try { 486 $network = "{$ip}/{$cidr}"; 487 $networkInt = ip2long($ip); 488 $mask = (0xFFFFFFFF << (32 - $cidr)) & 0xFFFFFFFF; 489 $networkAddress = long2ip($networkInt & $mask); 490 $broadcastAddress = long2ip($networkInt | (~$mask & 0xFFFFFFFF)); 491 492 return [ 493 'network_address' => $networkAddress, 494 'broadcast_address' => $broadcastAddress, 495 'subnet_mask' => long2ip($mask), 496 'num_addresses' => pow(2, 32 - $cidr), 497 'usable_hosts' => pow(2, 32 - $cidr) - 2, 498 'first_host' => long2ip(($networkInt & $mask) + 1), 499 'last_host' => long2ip(($networkInt | (~$mask & 0xFFFFFFFF)) - 1) 500 ]; 501 } catch (Exception $e) { 502 throw new Exception("无法解析子网信息: " . $e->getMessage()); 503 } 504 } 505} 506 507// 使用示例 508function main() { 509 $calculator = new SubnetCalculator(); 510 511 echo "=== 子网划分工具 - PHP版本 ===\n"; 512 513 // VLSM示例 514 echo "\n--- VLSM子网划分示例 ---\n"; 515 try { 516 $vlsmResult = $calculator->calculateVLSM('192.168.1.0/24', [ 517 ['name' => '销售部', 'hosts' => 50], 518 ['name' => '技术部', 'hosts' => 30], 519 ['name' => '财务部', 'hosts' => 10], 520 ['name' => '人事部', 'hosts' => 5] 521 ], [ 522 'optimize_order' => true, 523 'include_network_broadcast' => true 524 ]); 525 526 echo "VLSM结果:\n"; 527 foreach ($vlsmResult['subnets'] as $subnet) { 528 echo " {$subnet['name']}: {$subnet['network_address']}/{$subnet['cidr']} ({$subnet['first_host']} - {$subnet['last_host']})\n"; 529 } 530 echo "汇总: 原始网络={$vlsmResult['summary']['original_network']}, 总子网数={$vlsmResult['summary']['total_subnets']}, 总主机数={$vlsmResult['summary']['total_hosts']}, 利用率={$vlsmResult['summary']['utilization']}%\n"; 531 } catch (Exception $e) { 532 echo "VLSM错误: " . $e->getMessage() . "\n"; 533 } 534 535 // 子网合并示例 536 echo "\n--- 子网合并示例 ---\n"; 537 try { 538 $mergeResult = $calculator->mergeSubnets([ 539 '192.168.1.0/26', 540 '192.168.1.64/26', 541 '192.168.1.128/26', 542 '192.168.1.192/26' 543 ], [ 544 'merge_adjacent' => true, 545 'merge_contiguous' => true, 546 'validate_subnets' => true 547 ]); 548 549 echo "合并结果:\n"; 550 foreach ($mergeResult['merged_subnets'] as $merged) { 551 echo " {$merged['network']} (包含: " . implode(', ', $merged['original_subnets']) . ")\n"; 552 } 553 echo "汇总: 原子网数={$mergeResult['summary']['original_count']}, 合并后={$mergeResult['summary']['merged_count']}, 减少={$mergeResult['summary']['reduction']}, 利用率={$mergeResult['summary']['utilization']}%\n"; 554 } catch (Exception $e) { 555 echo "合并错误: " . $e->getMessage() . "\n"; 556 } 557 558 // 超网计算示例 559 echo "\n--- 超网计算示例 ---\n"; 560 try { 561 $supernetResult = $calculator->calculateSupernet('192.168.1.10', '192.168.1.50'); 562 echo "超网结果: {$supernetResult['network_address']}/{$supernetResult['cidr']}\n"; 563 echo "详细信息: {$supernetResult['details']}\n"; 564 } catch (Exception $e) { 565 echo "超网错误: " . $e->getMessage() . "\n"; 566 } 567 568 // 网络规划示例 569 echo "\n--- 网络规划示例 ---\n"; 570 try { 571 $planningResult = $calculator->generateNetworkPlan('10.0.0.0/8', [ 572 ['name' => '总部', 'size' => 200], 573 ['name' => '分公司A', 'size' => 100], 574 ['name' => '分公司B', 'size' => 80], 575 ['name' => '研发中心', 'size' => 150] 576 ], [ 577 'optimize_utilization' => true, 578 'reserve_space' => true 579 ]); 580 581 echo "规划结果:\n"; 582 foreach ($planningResult['departments'] as $dept) { 583 echo " {$dept['name']}: {$dept['network_address']}/{$dept['cidr']} ({$dept['allocated_hosts']} 主机)\n"; 584 } 585 echo "汇总: 总空间={$planningResult['summary']['total_space']}, 已分配={$planningResult['summary']['allocated_space']}, 剩余={$planningResult['summary']['remaining_space']}, 利用率={$planningResult['summary']['utilization']}%, 部门数={$planningResult['summary']['department_count']}\n"; 586 } catch (Exception $e) { 587 echo "规划错误: " . $e->getMessage() . "\n"; 588 } 589} 590 591// 如果直接运行此文件,则执行主函数 592if (basename(__FILE__) == basename($_SERVER['SCRIPT_NAME'])) { 593 main(); 594} 595?>
-
subnet_calculator (PY)
1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3""" 4子网划分工具 - Python版本 5支持VLSM可变长子网掩码、子网合并、超网计算、网络规划等功能 6""" 7import re 8import ipaddress 9from typing import Dict, List, Tuple, Optional, Union 10import math 11 12 13class SubnetCalculator: 14 """子网划分计算器类""" 15 16 def __init__(self): 17 self.ip_regex = re.compile(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') 18 self.cidr_regex = re.compile(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$') 19 20 def validate_ip(self, ip: str) -> bool: 21 """验证IP地址格式""" 22 return bool(self.ip_regex.match(ip)) 23 24 def validate_cidr(self, cidr: str) -> bool: 25 """验证CIDR格式""" 26 return bool(self.cidr_regex.match(cidr)) 27 28 def ip_to_int(self, ip: str) -> int: 29 """IP地址转换为整数""" 30 if not self.validate_ip(ip): 31 raise ValueError('无效的IP地址格式') 32 33 parts = [int(part) for part in ip.split('.')] 34 return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3] 35 36 def int_to_ip(self, ip_int: int) -> str: 37 """整数转换为IP地址""" 38 return '.'.join([ 39 str((ip_int >> 24) & 255), 40 str((ip_int >> 16) & 255), 41 str((ip_int >> 8) & 255), 42 str(ip_int & 255) 43 ]) 44 45 def get_subnet_mask(self, cidr: int) -> str: 46 """获取子网掩码""" 47 mask = (0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF 48 return self.int_to_ip(mask) 49 50 def get_network_address(self, ip: str, cidr: int) -> str: 51 """获取网络地址""" 52 ip_int = self.ip_to_int(ip) 53 mask = (0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF 54 network_int = ip_int & mask 55 return self.int_to_ip(network_int) 56 57 def get_broadcast_address(self, ip: str, cidr: int) -> str: 58 """获取广播地址""" 59 ip_int = self.ip_to_int(ip) 60 mask = (0xFFFFFFFF << (32 - cidr)) & 0xFFFFFFFF 61 broadcast_int = ip_int | (~mask & 0xFFFFFFFF) 62 return self.int_to_ip(broadcast_int) 63 64 def get_first_host(self, ip: str, cidr: int) -> str: 65 """获取第一个可用主机地址""" 66 network_int = self.ip_to_int(self.get_network_address(ip, cidr)) 67 return self.int_to_ip(network_int + 1) 68 69 def get_last_host(self, ip: str, cidr: int) -> str: 70 """获取最后一个可用主机地址""" 71 broadcast_int = self.ip_to_int(self.get_broadcast_address(ip, cidr)) 72 return self.int_to_ip(broadcast_int - 1) 73 74 def get_usable_hosts(self, cidr: int) -> int: 75 """计算可用主机数量""" 76 return 2 ** (32 - cidr) - 2 77 78 def parse_cidr(self, cidr: str) -> Dict[str, Union[str, int]]: 79 """解析CIDR格式""" 80 if not self.validate_cidr(cidr): 81 raise ValueError('无效的CIDR格式') 82 83 ip, mask_bits = cidr.split('/') 84 return { 85 'ip': ip, 86 'cidr': int(mask_bits), 87 'subnet_mask': self.get_subnet_mask(int(mask_bits)) 88 } 89 90 def calculate_vlsm(self, network_cidr: str, subnet_requirements: List[Dict], 91 options: Optional[Dict] = None) -> Dict: 92 """VLSM子网划分""" 93 if options is None: 94 options = {} 95 96 parsed = self.parse_cidr(network_cidr) 97 network_ip = parsed['ip'] 98 network_cidr_bits = parsed['cidr'] 99 100 network_int = self.ip_to_int(self.get_network_address(network_ip, network_cidr_bits)) 101 total_hosts = self.get_usable_hosts(network_cidr_bits) 102 103 # 按主机数量排序(如果需要) 104 sorted_requirements = sorted(subnet_requirements, 105 key=lambda x: x['hosts'], 106 reverse=options.get('optimize_order', True)) 107 108 # 计算每个子网需要的掩码位数 109 subnets = [] 110 current_network_int = network_int 111 112 for requirement in sorted_requirements: 113 required_hosts = requirement['hosts'] + (2 if options.get('include_network_broadcast', True) else 0) 114 required_cidr = 32 - math.ceil(math.log2(required_hosts)) 115 116 if required_cidr < network_cidr_bits: 117 raise ValueError(f"子网 {requirement['name']} 需要的主机数超出可用空间") 118 119 subnet_network_ip = self.int_to_ip(current_network_int) 120 subnet_mask = self.get_subnet_mask(required_cidr) 121 subnet_hosts = self.get_usable_hosts(required_cidr) 122 123 subnets.append({ 124 'name': requirement['name'], 125 'network_address': subnet_network_ip, 126 'subnet_mask': subnet_mask, 127 'cidr': required_cidr, 128 'first_host': self.get_first_host(subnet_network_ip, required_cidr), 129 'last_host': self.get_last_host(subnet_network_ip, required_cidr), 130 'broadcast_address': self.get_broadcast_address(subnet_network_ip, required_cidr), 131 'usable_hosts': subnet_hosts, 132 'required_hosts': requirement['hosts'] 133 }) 134 135 # 计算下一个子网的起始地址 136 subnet_size = 2 ** (32 - required_cidr) 137 current_network_int += subnet_size 138 139 # 计算汇总信息 140 total_required_hosts = sum(req['hosts'] for req in sorted_requirements) 141 utilization = round((total_required_hosts / total_hosts) * 100, 2) 142 143 return { 144 'subnets': subnets, 145 'summary': { 146 'original_network': network_cidr, 147 'total_subnets': len(subnets), 148 'total_hosts': total_required_hosts, 149 'utilization': utilization 150 }, 151 'details': f"VLSM划分完成,共创建 {len(subnets)} 个子网,地址利用率 {utilization}%" 152 } 153 154 def merge_subnets(self, subnet_list: List[str], options: Optional[Dict] = None) -> Dict: 155 """子网合并""" 156 if options is None: 157 options = {} 158 159 subnets = [] 160 161 # 解析子网列表 162 for subnet_str in subnet_list: 163 if not self.validate_cidr(subnet_str): 164 if options.get('validate_subnets', True): 165 raise ValueError(f"无效的子网格式: {subnet_str}") 166 continue 167 168 parsed = self.parse_cidr(subnet_str) 169 network_ip = self.get_network_address(parsed['ip'], parsed['cidr']) 170 subnets.append({ 171 'network': subnet_str, 172 'network_ip': network_ip, 173 'cidr': parsed['cidr'], 174 'network_int': self.ip_to_int(network_ip), 175 'host_count': self.get_usable_hosts(parsed['cidr']) 176 }) 177 178 if not subnets: 179 raise ValueError('没有有效的子网可以合并') 180 181 # 按网络地址排序 182 subnets.sort(key=lambda x: x['network_int']) 183 184 merged_subnets = [] 185 current_group = [subnets[0]] 186 187 for i in range(1, len(subnets)): 188 current = subnets[i] 189 last = current_group[-1] 190 191 # 检查是否相邻或连续 192 is_adjacent = (options.get('merge_adjacent', True) and 193 self._are_subnets_adjacent(last, current)) 194 is_contiguous = (options.get('merge_contiguous', True) and 195 self._are_subnets_contiguous(last, current)) 196 197 if is_adjacent or is_contiguous: 198 current_group.append(current) 199 else: 200 # 合并当前组 201 if len(current_group) > 1: 202 merged_subnets.append(self._merge_subnet_group(current_group)) 203 else: 204 merged_subnets.append({ 205 'network': current_group[0]['network'], 206 'original_subnets': [current_group[0]['network']], 207 'host_count': current_group[0]['host_count'] 208 }) 209 current_group = [current] 210 211 # 处理最后一组 212 if len(current_group) > 1: 213 merged_subnets.append(self._merge_subnet_group(current_group)) 214 else: 215 merged_subnets.append({ 216 'network': current_group[0]['network'], 217 'original_subnets': [current_group[0]['network']], 218 'host_count': current_group[0]['host_count'] 219 }) 220 221 # 计算汇总信息 222 original_count = len(subnets) 223 merged_count = len(merged_subnets) 224 reduction = original_count - merged_count 225 total_hosts = sum(subnet['host_count'] for subnet in merged_subnets) 226 227 return { 228 'merged_subnets': merged_subnets, 229 'summary': { 230 'original_count': original_count, 231 'merged_count': merged_count, 232 'reduction': reduction, 233 'total_hosts': total_hosts, 234 'utilization': round((total_hosts / (2**32 - 1)) * 100, 4) 235 }, 236 'details': f"合并完成,从 {original_count} 个子网合并为 {merged_count} 个,减少 {reduction} 个" 237 } 238 239 def _are_subnets_adjacent(self, subnet1: Dict, subnet2: Dict) -> bool: 240 """检查两个子网是否相邻""" 241 broadcast1 = self.ip_to_int(self.get_broadcast_address(subnet1['network_ip'], subnet1['cidr'])) 242 network2 = subnet2['network_int'] 243 return network2 == broadcast1 + 1 244 245 def _are_subnets_contiguous(self, subnet1: Dict, subnet2: Dict) -> bool: 246 """检查两个子网是否连续""" 247 broadcast1 = self.ip_to_int(self.get_broadcast_address(subnet1['network_ip'], subnet1['cidr'])) 248 network2 = subnet2['network_int'] 249 return network2 <= broadcast1 + 1 250 251 def _merge_subnet_group(self, subnet_group: List[Dict]) -> Dict: 252 """合并子网组""" 253 first = subnet_group[0] 254 last = subnet_group[-1] 255 last_broadcast = self.ip_to_int(self.get_broadcast_address(last['network_ip'], last['cidr'])) 256 257 # 计算合并后的CIDR 258 range_size = last_broadcast - first['network_int'] + 1 259 merged_cidr = 32 - math.ceil(math.log2(range_size)) 260 261 merged_network_ip = self.int_to_ip(first['network_int']) 262 merged_network = f"{merged_network_ip}/{merged_cidr}" 263 merged_host_count = self.get_usable_hosts(merged_cidr) 264 265 return { 266 'network': merged_network, 267 'original_subnets': [s['network'] for s in subnet_group], 268 'host_count': merged_host_count 269 } 270 271 def calculate_supernet(self, start_ip: str, end_ip: str, 272 options: Optional[Dict] = None) -> Dict: 273 """超网计算""" 274 if options is None: 275 options = {} 276 277 if not self.validate_ip(start_ip) or not self.validate_ip(end_ip): 278 raise ValueError('无效的IP地址格式') 279 280 start_int = self.ip_to_int(start_ip) 281 end_int = self.ip_to_int(end_ip) 282 283 if start_int > end_int: 284 raise ValueError('起始IP不能大于结束IP') 285 286 # 计算包含该范围的最小超网 287 range_size = end_int - start_int + 1 288 required_cidr = 32 - math.ceil(math.log2(range_size)) 289 290 # 找到包含该范围的最小网络地址 291 mask = (0xFFFFFFFF << (32 - required_cidr)) & 0xFFFFFFFF 292 network_int = start_int & mask 293 network_ip = self.int_to_ip(network_int) 294 295 # 验证该网络是否包含整个范围 296 broadcast_int = network_int | (~mask & 0xFFFFFFFF) 297 if broadcast_int < end_int: 298 # 需要更大的网络 299 new_cidr = required_cidr - 1 300 new_mask = (0xFFFFFFFF << (32 - new_cidr)) & 0xFFFFFFFF 301 new_network_int = start_int & new_mask 302 new_network_ip = self.int_to_ip(new_network_int) 303 304 return { 305 'network_address': new_network_ip, 306 'subnet_mask': self.get_subnet_mask(new_cidr), 307 'cidr': new_cidr, 308 'broadcast_address': self.int_to_ip(new_network_int | (~new_mask & 0xFFFFFFFF)), 309 'first_host': self.int_to_ip(new_network_int + 1), 310 'last_host': self.int_to_ip((new_network_int | (~new_mask & 0xFFFFFFFF)) - 1), 311 'total_hosts': self.get_usable_hosts(new_cidr), 312 'start_ip': start_ip, 313 'end_ip': end_ip, 314 'details': f"计算得到包含范围 {start_ip}-{end_ip} 的最小超网 {new_network_ip}/{new_cidr}" 315 } 316 317 return { 318 'network_address': network_ip, 319 'subnet_mask': self.get_subnet_mask(required_cidr), 320 'cidr': required_cidr, 321 'broadcast_address': self.int_to_ip(broadcast_int), 322 'first_host': self.int_to_ip(network_int + 1), 323 'last_host': self.int_to_ip(broadcast_int - 1), 324 'total_hosts': self.get_usable_hosts(required_cidr), 325 'start_ip': start_ip, 326 'end_ip': end_ip, 327 'details': f"计算得到包含范围 {start_ip}-{end_ip} 的最小超网 {network_ip}/{required_cidr}" 328 } 329 330 def generate_network_plan(self, address_space: str, department_requirements: List[Dict], 331 options: Optional[Dict] = None) -> Dict: 332 """网络规划""" 333 if options is None: 334 options = {} 335 336 parsed = self.parse_cidr(address_space) 337 network_ip = parsed['ip'] 338 network_cidr_bits = parsed['cidr'] 339 340 network_int = self.ip_to_int(self.get_network_address(network_ip, network_cidr_bits)) 341 total_space = self.get_usable_hosts(network_cidr_bits) 342 343 # 按部门大小排序 344 sorted_departments = sorted(department_requirements, 345 key=lambda x: x['size'], 346 reverse=options.get('optimize_utilization', True)) 347 348 departments = [] 349 current_network_int = network_int 350 allocated_space = 0 351 352 for dept in sorted_departments: 353 required_hosts = dept['size'] + (math.ceil(dept['size'] * 0.2) if options.get('reserve_space', True) else 0) 354 required_cidr = 32 - math.ceil(math.log2(required_hosts + 2)) # +2 for network and broadcast 355 356 if required_cidr < network_cidr_bits: 357 raise ValueError(f"部门 {dept['name']} 需要的主机数超出可用空间") 358 359 dept_network_ip = self.int_to_ip(current_network_int) 360 dept_subnet_mask = self.get_subnet_mask(required_cidr) 361 dept_hosts = self.get_usable_hosts(required_cidr) 362 363 departments.append({ 364 'name': dept['name'], 365 'network_address': dept_network_ip, 366 'subnet_mask': dept_subnet_mask, 367 'cidr': required_cidr, 368 'first_host': self.get_first_host(dept_network_ip, required_cidr), 369 'last_host': self.get_last_host(dept_network_ip, required_cidr), 370 'allocated_hosts': dept['size'], 371 'total_hosts': dept_hosts 372 }) 373 374 allocated_space += dept_hosts 375 subnet_size = 2 ** (32 - required_cidr) 376 current_network_int += subnet_size 377 378 remaining_space = total_space - allocated_space 379 utilization = round((allocated_space / total_space) * 100, 2) 380 381 return { 382 'departments': departments, 383 'summary': { 384 'total_space': total_space, 385 'allocated_space': allocated_space, 386 'remaining_space': remaining_space, 387 'utilization': utilization, 388 'department_count': len(departments) 389 }, 390 'details': f"网络规划完成,共分配 {len(departments)} 个部门,地址利用率 {utilization}%,剩余空间 {remaining_space} 个主机" 391 } 392 393 def get_subnet_info(self, ip: str, cidr: int) -> Dict: 394 """获取子网详细信息(使用ipaddress模块)""" 395 try: 396 network = ipaddress.IPv4Network(f"{ip}/{cidr}", strict=False) 397 return { 398 'network_address': str(network.network_address), 399 'broadcast_address': str(network.broadcast_address), 400 'subnet_mask': str(network.netmask), 401 'num_addresses': network.num_addresses, 402 'usable_hosts': network.num_addresses - 2, 403 'first_host': str(network.network_address + 1), 404 'last_host': str(network.broadcast_address - 1) 405 } 406 except Exception as e: 407 raise ValueError(f"无法解析子网信息: {e}") 408 409 410def main(): 411 """主函数 - 演示各种功能""" 412 calculator = SubnetCalculator() 413 414 print("=== 子网划分工具 - Python版本 ===") 415 416 # VLSM示例 417 print("\n--- VLSM子网划分示例 ---") 418 try: 419 vlsm_result = calculator.calculate_vlsm('192.168.1.0/24', [ 420 {'name': '销售部', 'hosts': 50}, 421 {'name': '技术部', 'hosts': 30}, 422 {'name': '财务部', 'hosts': 10}, 423 {'name': '人事部', 'hosts': 5} 424 ]) 425 print("VLSM结果:") 426 for subnet in vlsm_result['subnets']: 427 print(f" {subnet['name']}: {subnet['network_address']}/{subnet['cidr']} " 428 f"({subnet['first_host']} - {subnet['last_host']})") 429 print(f"汇总: {vlsm_result['summary']}") 430 except Exception as e: 431 print(f"VLSM错误: {e}") 432 433 # 子网合并示例 434 print("\n--- 子网合并示例 ---") 435 try: 436 merge_result = calculator.merge_subnets([ 437 '192.168.1.0/26', 438 '192.168.1.64/26', 439 '192.168.1.128/26', 440 '192.168.1.192/26' 441 ]) 442 print("合并结果:") 443 for merged in merge_result['merged_subnets']: 444 print(f" {merged['network']} (包含: {', '.join(merged['original_subnets'])})") 445 print(f"汇总: {merge_result['summary']}") 446 except Exception as e: 447 print(f"合并错误: {e}") 448 449 # 超网计算示例 450 print("\n--- 超网计算示例 ---") 451 try: 452 supernet_result = calculator.calculate_supernet('192.168.1.10', '192.168.1.50') 453 print(f"超网结果: {supernet_result['network_address']}/{supernet_result['cidr']}") 454 print(f"详细信息: {supernet_result}") 455 except Exception as e: 456 print(f"超网错误: {e}") 457 458 # 网络规划示例 459 print("\n--- 网络规划示例 ---") 460 try: 461 planning_result = calculator.generate_network_plan('10.0.0.0/8', [ 462 {'name': '总部', 'size': 200}, 463 {'name': '分公司A', 'size': 100}, 464 {'name': '分公司B', 'size': 80}, 465 {'name': '研发中心', 'size': 150} 466 ]) 467 print("规划结果:") 468 for dept in planning_result['departments']: 469 print(f" {dept['name']}: {dept['network_address']}/{dept['cidr']} " 470 f"({dept['allocated_hosts']} 主机)") 471 print(f"汇总: {planning_result['summary']}") 472 except Exception as e: 473 print(f"规划错误: {e}") 474 475 476if __name__ == "__main__": 477 main()