0

0

高效判断端口范围集合是否相交:三种算法方案对比与推荐实现

心靈之曲

心靈之曲

发布时间:2026-01-31 12:53:56

|

301人浏览过

|

来源于php中文网

原创

高效判断端口范围集合是否相交:三种算法方案对比与推荐实现

本文探讨在防火墙访问控制列表(acl)分析场景下,如何高效判断一组目标端口(含单值或范围)是否与已有的服务端口集合存在交集,重点对比集合展开、区间排序扫描与事件点计数三种策略的时空复杂度与工程适用性。

网络安全策略分析中,常需验证某组端口(如 {"5672", "15672-15674"})是否与防火墙 ACL 中定义的服务端口(如 {"20-22", "443", "8080-8088", "10000-65535"})存在交集。由于端口表示形式混合了单值(443)和闭区间(20-22),直接字符串匹配无效,必须进行数值语义层面的区间重叠判定。以下是经过严谨复杂度分析后推荐的最优实践方案。

✅ 推荐方案:基于有序区间列表的二分查找重叠检测(Approach 2)

该方案将 ACL 端口统一标准化为 [start, end] 形式,构建按 start 排序的不可变区间列表(一次构建,多次复用),对每个待查目标端口区间,通过二分查找快速定位潜在重叠候选,再做精确区间交集判断。

核心优势:

Build AI
Build AI

为您的业务构建自己的AI应用程序。不需要任何技术技能。

下载
  • 时间高效:预处理 O(n log n),每次查询仅 O(m log n)(n = ACL 区间数,m = 目标区间数),远优于全量端口展开;
  • 内存友好:仅存储 n + m 个整数对,避免生成最多 65536 个元素的 HashSet;
  • 工程稳健:逻辑清晰、边界易控、无哈希冲突或大数组分配风险。

Java 示例实现:

import java.util.*;

public class PortRangeIntersector {
    // 预处理:将 String[] 转为排序后的 [start, end] 列表
    public static List parseAndSortRanges(String[] ranges) {
        List list = new ArrayList<>();
        for (String r : ranges) {
            String[] parts = r.trim().split("-", 2);
            int start = Integer.parseInt(parts[0].trim());
            int end = parts.length == 2 ? Integer.parseInt(parts[1].trim()) : start;
            list.add(new int[]{start, end});
        }
        list.sort(Comparator.comparingInt(a -> a[0])); // 按起始端口升序
        return list;
    }

    // 判断 targetRange 是否与 sortedAclRanges 存在交集
    public static boolean hasIntersection(int[] targetRange, List sortedAclRanges) {
        int left = 0, right = sortedAclRanges.size() - 1;
        int tgtStart = targetRange[0], tgtEnd = targetRange[1];

        while (left <= right) {
            int mid = left + (right - left) / 2;
            int[] acl = sortedAclRanges.get(mid);

            // 快速剪枝:若 acl 完全在 target 左侧 → 向右搜
            if (acl[1] < tgtStart) {
                left = mid + 1;
            } 
            // 若 acl 完全在 target 右侧 → 向左搜
            else if (acl[0] > tgtEnd) {
                right = mid - 1;
            } 
            // 否则:存在重叠(区间交集非空 ⇔ !(a.end < b.start || b.end < a.start))
            else {
                return true;
            }
        }
        return false;
    }

    // 主入口:判断 entireTargetRanges 是否与 ACL 有任何交集
    public static boolean intersects(String[] targetPorts, List sortedAclRanges) {
        for (String t : targetPorts) {
            int[] range = parseSingleRange(t);
            if (hasIntersection(range, sortedAclRanges)) {
                return true;
            }
        }
        return false;
    }

    private static int[] parseSingleRange(String s) {
        String[] p = s.trim().split("-", 2);
        int start = Integer.parseInt(p[0].trim());
        int end = p.length == 2 ? Integer.parseInt(p[1].trim()) : start;
        return new int[]{start, end};
    }

    // 使用示例
    public static void main(String[] args) {
        String[] aclPorts = {"20-22", "443", "8080-8088", "10000-65535"};
        String[] myPorts = {"5672", "15672-15674"};

        List aclRanges = parseAndSortRanges(aclPorts);
        boolean result = intersects(myPorts, aclRanges);
        System.out.println("存在交集: " + result); // 输出: false
    }
}

⚠️ 其他方案简评

  • Approach 1(HashSet 展开):仅适用于极小规模 ACL(如
  • Approach 3(事件点扫描):理论优雅(类似“线段覆盖”问题),但需合并排序 n+m 个端点,实际性能弱于 Approach 2(O((n+m) log(n+m)) vs O(m log n)),且代码更冗长、调试成本高。

✅ 最佳实践建议

  • 预处理一次,查询多次:ACL 通常静态或低频更新,务必缓存 sortedAclRanges;
  • 校验输入合法性:生产环境需增加 0 ≤ port ≤ 65535 范围检查与格式异常捕获;
  • 扩展性考虑:如需支持通配符(any)、排除规则(negate),应在区间模型上叠加布尔逻辑层,而非退回字符串解析

综上,基于排序区间 + 二分查找的重叠检测是平衡性能、内存与可维护性的首选方案,特别契合防火墙策略分析这类对实时性与资源敏感的系统场景。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1503

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

625

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

655

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

610

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

172

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

83

2025.08.07

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

30

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8.1万人学习

Java 教程
Java 教程

共578课时 | 54万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号