尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python端口扫描与终端监控实战:原理、代码与避坑
简介面向网络安全课程设计场景的一份端口扫描实现代码适合计算机网络或安全方向的学生完成终端监控类项目时参考借鉴。压缩包内共十七个文件主要以C源码为主包括头文件、源程序文件、对话框资源文件及工程配置文件等整体约二十九KB结构紧凑便于直接加载到Visual C工程中快速运行与调试。已有二百三十八人学习与下载。代码实现了对指定IP地址、指定端口和指定线程数的扫描功能同时简要梳理了端口扫描的基本原理能帮助读者理解入侵者扫描目标主机的常见方式并据此加强本机访问控制与安全配置。配套的工程文件与资源脚本齐全可快速查看界面与逻辑的对应关系适合在课程报告或答辩演示中作为基础功能模块直接复用。1. 课程设计拿到“终端监控端口扫描”先搞明白要交什么端口扫描是网络安全课程设计里出镜率最高的一类题目挂上“终端监控”这个前缀后很多人就懵了到底是让我写一个扫描器还是让我写一个监控系统我的经验是这类题真正想让你交的东西是三件事能跑的扫描代码、能讲清楚的扫描原理以及一份“扫描结果怎么被终端侧使用”的说明。端口扫描的本质是探测目标主机的端口状态而终端监控关心的是这些端口状态的变化两者拼在一起才是一个完整的课程设计。适合做这个题的人是对 TCP/IP 协议有基本概念、能写 Python、但还没系统写过网络安全工具的同学。如果你只会调用现成的扫描工具而不清楚底层逻辑答辩时很容易被问住。本文按“原理选型 → 代码落地 → 终端监控联动 → 避坑 → 验证与进阶”的顺序展开代码全部可直接运行参数也给到能改的程度。2. 端口扫描的原理与课程设计选型为什么不用 SYN 扫描2.1 端口扫描的本质三次握手和连接状态端口扫描做的事情本质上就是向目标主机的某个 TCP 端口发起连接尝试通过连接结果判断该端口的状态。这里绕不开 TCP 三次握手客户端发送 SYN服务端回复 SYNACK 表示愿意建立连接再回复 ACK 完成握手。如果目标端口关闭服务端内核会直接回复 RST连接建立失败。扫描的核心逻辑就是围绕“有没有收到 SYNACK”做判断。端口状态一般分三类open收到 SYNACK、closed收到 RST、filtered超时或被防火墙丢弃无任何响应。这个判断逻辑虽然简单但落实到代码上有几个关键点连接超时设置、目标 IP 的连通性前置判断、以及并发模型的选择。很多人在课程设计里犯的错是忽略 filtered 状态把超时一律归为端口关闭这在答辩时很容易被追问。常见扫描方式有三类。TCP Connect 扫描就是完整走完三次握手因为用了系统底层的 connect 系统调用准确率高但也会在目标系统留下完整的连接日志动静大。SYN 半开扫描只发 SYN 收到 SYNACK 后直接回 RST 断开不建立完整连接隐蔽性比前者强但需要自己构造 IP 头通常得用 raw socket。还有 UDP 扫描面向 DNS、SNMP 这类 UDP 服务但因为 UDP 无连接特性可靠性较差需要结合 ICMP Port Unreachable 信息判断复杂度较高。三类方式从实现难度上排序TCP Connect 最简单UDP 次之SYN 半开最难。对课程设计而言还要考虑运行环境——只要不是自己搭虚拟机做实验很多 Windows 环境下 raw socket 受限SYN 扫描不一定跑得起来。选型时先把这一点想清楚能省后面不少事。2.2 课程设计选 TCP Connect 多线程的三点理由第一点TCP Connect 扫描不依赖管理员权限普通用户权限就能执行 connect 系统调用。这意味着在任何一台开发机上跑代码不对运行环境提额外要求答辩演示不怕现场翻车。SYN 扫描需要 raw socketWindows 上还需要管理员权限加特殊库支持跨平台一致性差。第二点TCP Connect 的判定结果可直接对应三次握手的状态机校核逻辑更明确。课程设计答辩时老师最常问的一句话是“你怎么知道一个端口是开着的”TCP Connect 可以干脆回答“因为 connect 成功了说明对方完成了第二次握手”逻辑链条短且不易被追问到死角。第三点与终端监控场景的结合更自然。终端监控要的是确定性结果——端口开着就是开着而不是“好像开着”。TCP Connect 拿到的状态是通过系统级 API 确认过的写进监控基线和告警规则时语义清晰。相比 SYN 半开扫描后的“可能开放”判定TCP Connect 更适合做状态记录的原始数据来源。实现上的代价是扫描速度慢但可以靠多线程解决。课程设计阶段不需要考虑上千台主机的网络规模单主机 1000 个常见端口用 200 个线程去跑几秒内能完成性能完全够。2.3 存活探测与扫描端口范围的确定方法直接对目标 IP 全端口扫描不是好习惯一是慢二是动静大。常见做法是先做主机存活探测确认目标在线后再扫描。实现方式很简单用 ping 命令做 ICMP 探测或者对目标 IP 的 80、443、22 等常用端口做一次 TCP 连接尝试判断是否有人响应。某些环境下 ICMP 被禁用所以 TCP 探测是更可靠的兜底方案。端口范围的选择也有讲究。全段扫描 65535 个端口对课程设计演示来说太慢而且大部分高校实验环境只开放少数服务端口。比较合理的做法是扫描知名端口列表加一个区间参数比如默认扫 1-1024 的知名端口再允许通过命令行参数指定一个自定义区间。代码里预留一个端口列表常量后续想增加端口改这个列表就行。也可以按服务场景分批次扫描第一遍扫常见 Web 端口80、443、8080、8443第二遍扫远程管理端口22、3389、5900第三遍再扫数据库端口3306、5432、1433。这样扫描结果能直接对应到服务类型跟终端监控的资产台账对接时也更好解释。3. 端口扫描代码落地从最小可运行到终端监控可对接3.1 一个最小可运行的扫描核心实现先把最核心的单端口扫描逻辑写出来这段代码是整个程序的心脏后续的并发改造都基于它。用 Python 的 socket 模块实现connect_ex 方法的好处是连接失败只返回错误码不抛异常省去一层 try-except 的嵌套。import socket def scan_port(host, port, timeout2.0): 对单个端口进行 TCP Connect 扫描 host: 目标 IP 或域名 port: 目标端口 timeout: 连接超时秒数默认 2 秒 返回值: 端口状态字符串 open / closed / filtered sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) result sock.connect_ex((host, port)) if result 0: status open elif result 111: # ECONNREFUSED端口关闭 status closed else: status filtered # 超时或其他未知原因 sock.close() return status这段代码里最需要注意的参数是 timeout。设得太小比如 0.5 秒在目标主机负载高或网络延迟大的环境里会把正常开放的端口误判为 filtered设得太大比如 10 秒全端口扫描的耗时难以接受。我一般默认取 2 秒内网环境可以降到 1 秒跨网段扫描可以适当调大到 3 秒。connect_ex 的返回值判断也要说明一下0 表示连接成功端口开放111 表示连接被拒绝端口关闭其他值如 110ETIMEDOUT则表示目标无响应通常归为 filtered。代码里也可以判断 result 110 单独列出超时状态方便后续统计。3.2 用线程池把扫描提速代码与参数调整单端口连串扫描 1024 个端口一个端口等 2 秒超时全部跑完要几十分钟显然不可用。常见做法是用 concurrent.futures.ThreadPoolExecutor 做多线程并发扫描线程数控制在 200 到 500 之间同时设置合理的超时。from concurrent.futures import ThreadPoolExecutor, as_completed def scan_ports(host, ports, max_threads300, timeout2.0): 批量扫描端口返回 (port, status) 结果列表 max_threads: 并发线程数内网环境建议 300公网环境建议降到 100 results [] with ThreadPoolExecutor(max_threads) as executor: future_to_port { executor.submit(scan_port, host, port, timeout): port for port in ports } for future in as_completed(future_to_port): port future_to_port[future] try: status future.result() results.append((port, status)) except Exception as exc: # 单线程异常不应中断整体扫描 print(fport {port} scan error: {exc}) results.append((port, error)) return results线程数不是越大越好这是个常见的翻车点。线程开太多时本机文件描述符会先耗尽——Linux 下默认 ulimit 一般是 1024也就是同时最多打开约 1000 个 socket线程数超过这个上限就会报 “Too many open files” 错误。Windows 下虽然没有 ulimit但 GIL 的存在让大量线程的收益递减。300 是内网扫描的常用值公网建议 100-200目标主机性能差时要降得更低。as_completed 的作用是每完成一个线程任务就取一次结果而不是等全部完成再统一取。这样可以把结果做实时输出终端监控场景里能边扫边看进度。不要用 map 方法它虽然代码更短但会等所有任务返回中间任何一个任务卡住会导致整体等待。3.3 结果输出与终端监控的数据对接格式扫描结果只有打印在屏幕上是远远不够的终端监控场景里需要把结果落成结构化数据方便后续做基线对比和告警。建议输出 JSON 格式因为 JSON 自带了端口和状态的对应关系后续解析不费力气。import json import datetime def save_scan_result(host, results, filenameNone): 将扫描结果保存为 JSON 文件 每条记录包含: 目标主机、端口、状态、扫描时间 if filename is None: filename fscan_{host}_{datetime.datetime.now().strftime(%Y%m%d_%H%M%S)}.json data { host: host, timestamp: datetime.datetime.now().isoformat(), result: [ {port: port, status: status} for port, status in results ] } with open(filename, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) return filename这里要把扫描时间和目标主机写进记录因为终端监控的场景里数据一定有历史比对需求。文件名带时间戳是为了让每次扫描留下存档后续做趋势分析时直接按目录读取即可。对终端监控来说还有一层需要考虑每次扫描必须和上一次结果做差异对比。所以代码里再加一个输出变更集合的步骤——找出两次扫描之间状态发生变化的端口单独生成一个变更文件这个文件就是告警系统的数据源。差异对比逻辑不复杂遍历两个结果字典找 state 不同或新增/消失的端口即可。课程设计做到这一步已经超出单纯扫描器的体量能看出“终端监控”这四个字的分量。4. 终端监控视角扫描结果怎么变成监控能力4.1 终端监控的核心不是扫一次而是看变化很多人以为终端监控就是装个扫描器定时跑这个理解偏差会导致设计被评委质疑。终端监控的核心资产是端口基线——一台服务器正常工作时开放哪些端口、哪些服务对外可访问这个基线一旦建立监控的含义就变成了“对比当前扫描结果和基线找出差异”。最典型的变化类型有三种新增端口可能意味着有人在这台机器上启动了未授权服务端口消失可能意味着关键服务宕机或被停掉端口状态变化比如从 open 变为 filtered可能是防火墙配置调整或服务异常。这就是从“端口扫描”到“终端监控”的跨越——扫描器只是采集器监控系统才是决策者。4.2 设计一个最小可用的监控流程在课程设计里实现一个最小闭环定时扫描 → 结果落库 → 基线对比 → 异常告警。这个流程用 Python 的 schedule 库就能实现核心代码如下。import schedule import time import json # 全局变量用于保存上一次扫描结果 last_baseline {} def monitor_loop(host, ports, interval_minutes10): 定时执行扫描并与基线对比 interval_minutes: 扫描间隔默认 10 分钟一次 global last_baseline schedule.every(interval_minutes).minutes.do(run_check, host, ports) while True: schedule.run_pending() time.sleep(1) # 避免空闲轮询耗满 CPU def run_check(host, ports): 执行一次扫描并输出变更 global last_baseline current {port: status for port, status in scan_ports(host, ports)} if last_baseline: changes find_changes(last_baseline, current) if changes: print(f[ALERT] 发现 {len(changes)} 个端口状态变化) for change in changes: print(change) last_baseline current扫描间隔是监控系统里需要权衡的参数。密集扫描能更快发现变化但会加大目标主机的连接压力和本机资源消耗。10 分钟一次对内网终端监控够了对需要快速响应的场景可以压到 1 分钟公网扫描建议 30 分钟起步。find_changes 函数负责输出具体差异实现也比较直接def find_changes(before, after): 对比两次扫描结果返回变更描述列表 changes [] all_ports set(before.keys()) | set(after.keys()) for port in sorted(all_ports): old_status before.get(port, not_exist) new_status after.get(port, not_exist) if old_status ! new_status: changes.append(f端口 {port}: {old_status} - {new_status}) return changes4.3 服务指纹识别给端口名称而不是数字端口号只是入口终端监控的最终报告应该告诉运维人员“哪个服务变了”而不是“哪个端口变了”。给端口绑定服务名的功能通常叫服务指纹识别也叫 banner grabbing——连上开放端口后读取服务端返回的版本信息或欢迎信息。def grab_banner(host, port, timeout3.0): 连接目标端口并读取 Banner 信息 通过 Banner 判断运行的服务类型与版本号 try: sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((host, port)) sock.send(b\r\n) # 有些服务需要先发送请求才返回 Banner banner sock.recv(1024).decode(errorsreplace).strip() sock.close() return banner except Exception: return # 在扫描主循环中对 open 端口自动抓 Banner for port, status in scan_ports(192.168.1.10, range(1, 1024)): if status open: banner grab_banner(192.168.1.10, port) print(f端口 {port} 开放Banner: {banner or (无 Banner)})常见服务的 Banner 有明显的特征SSH 服务一般返回以 “SSH-2.0” 开头的字符串HTTP 服务返回 “HTTP/1.1 400 Bad Request” 或类似响应FTP 服务会返回 “220” 开头的欢迎信息。有了 Banner 再查对应端口号的服务映射表就能把扫描结果从端口维度提升到服务维度这会让整个课程设计的完整度和专业度显著提升。答辩时把这个功能演示一遍老师追问的意愿会明显降低。5. 课程设计避坑指南端口扫描常见的五个翻车现场5.1 线程数开太大扫描器先把自己的机器搞挂了现象扫描运行到一半程序报 “Too many open files” 错误甚至整个 Python 进程直接退出任务管理器一看本机的连接数飙到几千。原因每新建一个 socket 连接就会占用一个文件描述符Linux 默认 ulimit 限制一般是 1024。线程数是 500加上主进程本身打开的文件很快就撞上限。解决先用ulimit -n查看当前限制再把线程数设置为限制值减 200 的缓冲量。或者动态调整线程数比如扫描任务开始时先探测剩余可用文件描述符再按剩余量初始化线程池。课程设计里直接把线程数写死成 200是最省心的做法。5.2 目标主机宕机或不在线却把全端口记为 closed现象扫描结果里所有端口都是 closed看起来像是目标主机关闭了所有服务实际上这台机器压根没开机或者网络不同。原因目标主机不可达时connect_ex 返回的是 EHOSTUNREACH错误码 113或 ETIMEDOUT错误码 110如果代码里只判断了 0 和 111其他值一律归为 closed就产生了错误结果。解决先做主机存活探测目标无响应时直接终止扫描并提示“主机不可达”而不是继续扫。代码里把错误码 113、110 单独归类到 filtered不要混到 closed 里——open、closed、filtered 三种状态在监控基线里含义完全不同混淆会导致监控系统发出错误告警。5.3 扫描动静太大被安全防护日志记录并触发告警现象课程设计演示时一切正常但事后被告知在实验环境的审计日志里看到大量来自本机 IP 的异常连接记录目标主机的安全系统产生了告警事件。原因TCP Connect 扫描在目标系统上留下的是完整的连接日志而且高并发扫描会在短时间内产生大量连接记录。如果平台有入侵检测机制很容易把行为判定为端口扫描攻击。解决课程设计代码里加一个扫描时间间隔参数每扫完一个端口线程自动等待 50-100 毫秒再启动下一个任务显著降低连接频率。也可以在代码里明确注释仅在授权环境下对本机或虚拟实验主机执行扫描。答辩时要主动说明这一点反而能体现安全意识。5.4 把 filtered 状态误判为 open产生幽灵端口现象扫描结果显示某端口开放但手工 telnet 这个端口始终连不上重复扫描结果也不稳定。原因防火墙策略导致 SYN 被静默丢弃时connect_ex 返回超时错误。部分代码把“超时”错误理解为“端口可能开放”直接归入 open 或 unknown 状态在监控基线里就会留下一个不存在的端口记录。解决严格定义三分类逻辑超时归 filteredconnect 成功归 open收到 RST 归 closed。宁可把可疑状态标为 filtered也不要模棱两可地写成 unknown 或 open。监控告警里 filtered 可以是只记录不告警但 open 的错误判断会直接触发误报警这是最影响监控可信度的问题。5.5 超时时间全局统一导致跨网段扫描大量漏报现象内网目标扫得飞快且准确但扫描一段跨网段地址或负载较高的主机时结果里 open 端口数量明显偏少部分真实开放的服务被漏掉。原因统一用 2 秒超时但跨网段 RTT 延迟可能到几百毫秒加上目标主机并发连接处理能力有限正常完成三次握手的时间超过了超时阈值。解决把超时时间作为独立参数暴露出来扫描前先按 ping 的 RTT 预估一个合理值。内网用 1-1.5 秒跨网段调大到 3-5 秒。也可以在扫描端口列表中优先扫描常用端口把不常用端口放在后段常用端口使用更宽的超时。6. 验证你的扫描结果两步确认法和 SYN 扫描的不归路扫描器写完了输出了一堆 open 端口如何确认这些结果是真实的我用的是两步确认法。第一步挑几个扫描结果为 open 的端口手工用 netcat 或 Telnet 尝试连接确认能建立 TCP 连接。第二步对这几个端口执行服务指纹识别看看 Banner 是否和预期服务匹配——比如 22 端口的 Banner 包含 SSH 版本号基本可以确定没有误报。这种验证方法不仅仅是为了课程设计演示更是后续给终端监控系统设置告警规则的前提。如果学有余力有个进阶方向值得注意SYN 半开扫描。原理是在构造数据包阶段直接通过 socket 的 raw 模式发送 SYN 包收到 SYNACK 后不回 ACK 而是回 RST这样目标系统不会记录完整的连接。但实现需要构造 IP 头、计算校验和、处理内核可能直接回 RST 的干扰搞通顺要花不少时间。课程设计不建议把它作为主扫描器实现可以作为答辩时的原理扩展讲一段——这反而是加分项说明你不仅知道怎么实现还了解其他扫描方式的机理。写完这一段想收个尾端口扫描写代码本身也许不算难难点在验证逻辑严谨、状态分类清晰、异常场景想周全。我自己第一次做类似题目时就因为把所有非 open 状态一律归为 closed被答辩老师一句“那你怎么解释超时”问得说不出话。后来养成了一个习惯所有网络编程工具的输出都留足状态位拿到结果先怀疑再确认。希望这段踩坑经验能帮到你少走一段弯路。本文还有配套的精品资源点击获取
RELATED

相关推荐

PB12票据打印错位修复:DataWindow套打与三表参数校准实战

PB12票据打印错位修复:DataWindow套打与三表参数校准实战

简介:面向PowerBuilder程序员的PB12票据打印解决方案,针对12版数据窗口与报表功能,解决企业应用中的票据版式设计、数据填充、多页连续打印等实际需求,也适合需要开发自定义纸张票据的桌面系统。压缩包共18个文件,其中…

📅 2026/10/16 16:46:00
古典密码C实现:棋盘密码与凯撒密码轻量级嵌入式方案

古典密码C实现:棋盘密码与凯撒密码轻量级嵌入式方案

简介:本资源是一份面向密码学初学者与C语言编程入门者的古典加密算法实践代码包,聚焦棋盘密码(Playfair)与凯撒密码两大基础替换/移位加密机制的完整C实现,助力理解加密原理、掌握字符处理逻辑及算法编程思维。压缩包为…

📅 2026/10/16 16:46:00
从ONNX到NPU:Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K的OGA混合推理流水线深度解析

从ONNX到NPU:Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K的OGA混合推理流水线深度解析

【免费下载链接】Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K 项目地址: https://ai.gitcode.com/hf_mirrors/amd/Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K 点击查看 免费下载 本文深入解析 Llama-3.2-3B-Instruct 在 AMD Ryzen AI 平台上的 OGA 混合推理流水线。该…

📅 2026/10/16 16:46:00
MORE NEWS

更多资讯

📰

新媒体全链路运营工具选型常见问题解答

搭建新媒体账号矩阵时,很多团队在运营工具选型上存在困惑。从一键分发、账号矩阵管控到私信统一管理,不少运营人员不清楚工具该如何评估、落地。蚁小二作为覆盖全链路的新媒体运营工具,集成了分发、矩阵管控、私信管理能力。下面围绕新媒体工…

📰

MCreator 方块基础类型(Block Base)完全指南:参数禁用机制与默认值约定

低代码代码生成桌面应用游戏开发 【免费下载链接】MCreator MCreator is an open-source software used to make Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons, resource packs, and data packs using an intuitive easy-to-learn interface or with an in…

📰

具身智能中的协同机理研究(115):TVA-World与其他架构的十大本质区别

前沿技术探索:TVA智能体(简称TVA) TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&a…

📰

Python、数据分析、编程都是啥?——写给业务同学的知识百科

为什么业务也要懂这些 你大概率不是程序员,但你每天都在和“数据”打交道:对账、做表、拉数、写周报、找异常。本文想用大白话把三件事讲清楚——编程是什么、Python 是什么、数据分析又是什么,以及它们怎么帮你把“重复劳动”变成“自动完成…

📰

2026年阿里企业邮箱授权电话获取指南,本地服务商对接联系号码

企业采购阿里云企业邮箱时,通过正规授权渠道与本地服务商对接,是保障部署、迁移与售后质量的关键环节。本文梳理授权联络渠道的获取方式、本地服务商的对接流程与常见误区,帮助企业在不依赖单一号码的前提下,掌握合规、高效的联系…

📰

AI 训练图片素材供应商推荐|可商用版权图像数据集服务商清单

在人工智能模型迭代加速的当下,寻找可靠的AI训练图片素材供应商已成为企业研发的关键环节。可商用版权图像数据集服务商清单不仅是资源索引,更是合规安全的保障。面对海量数据需求,选择具备正版授权、多模态供给及专业清洗能力的供应商至关重…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬