From a94fa25b97b4cea9408c9e5c294730bbe1b9798c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=9C=E7=8E=9B?= <809610+duma520@users.noreply.github.com> Date: Tue, 13 Jan 2026 06:53:26 +0800 Subject: [PATCH] Create README.md --- README.md | 4384 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4384 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..526d1db --- /dev/null +++ b/README.md @@ -0,0 +1,4384 @@ +# iperf3 图形化工具 - 完整使用说明书 + +# 界面截图: + +image + +image + +image + +image + +image + + +## 📖 文档概述 + +### 文档性质 +本文档是 **iperf3 图形化工具** 的官方完整说明书,适用于各个阶层、各个行业、不同技术背景的用户。无论您是网络管理员、系统工程师、学生、教师、网络爱好者,还是只是想测试家庭网络性能的普通用户,本文档都能为您提供所需的指导。 + +### 作者信息 +- **作者**:杜玛 (Duma) +- **版权**:永久保留所有权利 +- **项目地址**:https://github.com/duma520 +- **问题报告**:通过 GitHub Issues 提交 +- **特别说明**:我们不提供私人邮箱支持,所有技术支持都通过公开渠道进行,以便其他用户也能受益。 + +### 文档特点 +1. **多层次内容**:从零基础入门到高级专业配置 +2. **多角度解读**:兼顾理论知识和实践操作 +3. **多示例说明**:丰富的实际应用场景示例 +4. **全功能覆盖**:详细解释每个选项和功能 +5. **问题导向**:针对常见问题提供解决方案 + +--- + +## 第一章:什么是 iperf3 图形化工具? + +### 1.1 iperf3 简介 +iperf3 是一个专业的网络性能测试工具,用于测量两个节点之间的最大 TCP/UDP 带宽性能。它是网络工程师、系统管理员和开发人员必备的工具之一。 + +**通俗解释**:就像用测速软件测试您的网速一样,iperf3 是专业的"网络测速仪",但功能更强大、更精确。 + +### 1.2 图形化工具的价值 +原始的 iperf3 是命令行工具,需要记住复杂的参数。本图形化工具提供了: +- **直观的界面**:无需记忆命令参数 +- **完整的参数支持**:支持所有 iperf3 选项 +- **结果可视化**:直观显示测试结果 +- **配置管理**:保存和加载测试配置 +- **历史记录**:追踪历次测试结果 + +### 1.3 适用人群 +1. **普通家庭用户**:测试家庭宽带速度、Wi-Fi 信号强度 +2. **网络爱好者**:学习网络知识、测试网络设备性能 +3. **IT 管理员**:诊断网络问题、监控网络性能 +4. **系统工程师**:容量规划、性能优化 +5. **开发人员**:测试应用程序的网络性能 +6. **学生/教师**:网络课程教学、实验 + +--- + +## 第二章:快速入门(5分钟上手) + +### 2.1 安装要求 +#### 必须安装: +1. **Python 3.6+** (如果显示版本错误,请升级Python) +2. **iperf3 程序** (这是实际执行测试的核心工具) + +#### 安装步骤: +**Windows 用户**: +1. 安装 Python:从 python.org 下载并安装 +2. 安装 iperf3:从 iperf.fr 下载 Windows 版本 +3. 将 iperf3.exe 放在系统 PATH 或程序所在目录 + +**Linux/macOS 用户**: +```bash +# Ubuntu/Debian +sudo apt-get install python3 python3-pip iperf3 + +# CentOS/RHEL +sudo yum install python3 python3-pip iperf3 + +# macOS +brew install python iperf3 +``` + +### 2.2 第一次运行 +1. **双击运行**:`iperf_gui.py` 或使用命令行 `python iperf_gui.py` +2. **界面介绍**: + - 顶部标签页:不同功能区域 + - 中间区域:参数配置 + - 底部按钮:开始/停止测试 + - 右侧结果区:显示测试结果 + +### 2.3 最简单的测试场景 +#### 场景1:测试本地网络回环 +1. 模式选择:"客户端" +2. 服务器地址输入:`127.0.0.1`(这是本机地址) +3. 点击"开始测试" + +**这是什么?** 测试您自己电脑的网络栈性能,确保工具正常工作。 + +#### 场景2:测试两台电脑之间的网络 +**准备两台电脑**(A 和 B): +1. **在电脑 B(服务器)**: + - 模式选择:"服务器" + - 点击"开始测试" + - 记下 B 的 IP 地址(如 192.168.1.100) + +2. **在电脑 A(客户端)**: + - 模式选择:"客户端" + - 服务器地址输入:`192.168.1.100`(B 的 IP) + - 点击"开始测试" + +**结果解读**:显示的是 A 到 B 的网络速度。如果您的网络是千兆(1Gbps),理想值应该是 940Mbps 左右(理论值的 94%)。 + +--- + +## 第三章:界面详解(标签页功能说明) + +### 3.1 "基础配置"标签页 +这是最常用的配置区域,包含网络测试的基本参数。 + +#### 3.1.1 测试模式 +- **客户端**:主动发起测试的一端 + - *适用场景*:测试从本地到服务器的速度 + - *举例*:测试从办公室电脑到公司服务器的网速 +- **服务器**:等待连接的一端 + - *适用场景*:让他人测试连接到您的速度 + - *举例*:您的朋友想测试从他家到您家的网络速度 + +**专业说明**: +- 客户端模式对应 `iperf3 -c` 命令 +- 服务器模式对应 `iperf3 -s` 命令 +- 一次完整的测试需要一端是服务器,另一端是客户端 + +#### 3.1.2 服务器地址 +- **格式**:IP 地址或域名 +- **示例**: + - `192.168.1.1`(局域网 IP) + - `10.0.0.1`(内网 IP) + - `www.example.com`(域名,会自动解析为 IP) + - `127.0.0.1`(本地回环地址,用于测试本机) + +**重要提示**: +- 如果服务器在 NAT 后面(如家庭路由器),需要端口转发 +- 确保防火墙允许 5201 端口(或您指定的端口) + +#### 3.1.3 端口 +- **默认值**:5201 +- **可修改范围**:1-65535 +- **为什么改端口?** + 1. 安全原因:避免使用默认端口 + 2. 多实例运行:同时运行多个测试 + 3. 端口冲突:5201 端口已被占用 + +**示例场景**: +- 家庭宽带测试:使用默认 5201 +- 企业环境:使用 15201 等非标准端口 +- 同时测试:A用5201,B用5202,C用5203... + +#### 3.1.4 协议选择 +- **TCP**:传输控制协议 + - *特点*:可靠、有序、错误重传 + - *适用*:网页浏览、文件下载、视频流 + - *测试内容*:实际可用带宽、延迟影响 +- **UDP**:用户数据报协议 + - *特点*:快速、无连接、可能丢包 + - *适用*:实时视频、语音通话、在线游戏 + - *测试内容*:最大吞吐量、丢包率、抖动 + +**专业对比**: +| 特性 | TCP | UDP | +|------|-----|-----| +| 可靠性 | 高(自动重传) | 低(不保证到达) | +| 速度 | 相对较慢 | 非常快 | +| 顺序性 | 保证顺序 | 不保证顺序 | +| 适用场景 | 文件传输、网页 | 实时应用、游戏 | +| 测试重点 | 实际带宽 | 最大带宽、质量 | + +#### 3.1.5 测试时间 +- **单位**:秒 +- **范围**:1-3600 秒(1秒到1小时) +- **建议值**: + - 快速测试:10-30 秒 + - 稳定性测试:300-600 秒(5-10分钟) + - 压力测试:3600 秒(1小时) + +**时间选择策略**: +1. **短时间测试**(10秒):快速检查 + - 优点:快速得到结果 + - 缺点:可能受瞬时波动影响 + - 适用:日常检查、故障初步排查 + +2. **中时间测试**(60秒):标准测试 + - 优点:结果相对稳定 + - 缺点:需要等待 + - 适用:网络验收、性能评估 + +3. **长时间测试**(300秒以上):稳定性测试 + - 优点:反映真实稳定性能 + - 缺点:耗时较长 + - 适用:链路稳定性评估、QoS验证 + +**专业建议**: +- 对于波动较大的网络(如无线),建议测试时间 ≥ 30秒 +- 对于需要精确测量的场景(如SLA验证),建议 ≥ 300秒 +- TCP测试需要足够时间建立稳定传输速率 + +#### 3.1.6 并行流 +- **是什么**:同时建立多个连接进行测试 +- **范围**:1-128 个流 +- **默认值**:1 +- **单位**:个连接 + +**通俗解释**: +想象一条公路: +- 1个流 = 1条车道 +- 4个流 = 4条车道同时通行 +- 结果 = 总通行能力 + +**实际应用场景**: +1. **单流(默认)**: + - 测试单连接性能 + - 模拟普通文件下载 + - 结果反映单连接最大速度 + +2. **多流(建议4-8)**: + - 测试多用户同时访问 + - 模拟实际应用场景(如视频会议+文件传输) + - 更能反映真实网络性能 + +3. **大量流(16-32)**: + - 压力测试 + - 测试网络设备并发处理能力 + - 专业性能评估 + +**技术原理**: +``` +单流:客户端 ------------ 服务器 +多流:客户端 ---流1--- 服务器 + ---流2--- + ---流3--- +``` + +**示例设置建议**: +- 家庭网络测试:1-4个流 +- 企业网络评估:8-16个流 +- 数据中心测试:16-32个流 +- 极限压力测试:32-128个流 + +**注意事项**: +1. 过多的流可能导致: + - 路由器/交换机CPU负载过高 + - 测试结果反而下降 + - 影响其他网络应用 + +2. 流数量与测试结果的关系: + - 初期:增加流数量,总带宽增加 + - 最佳点:达到最大带宽 + - 后期:增加流,带宽不再增加甚至下降 + +3. 发现最佳流数量: + 推荐使用"阶梯测试法": + ``` + 第1次:1个流 → 记录结果 + 第2次:4个流 → 记录结果 + 第3次:8个流 → 记录结果 + 第4次:16个流 → 记录结果 + 比较结果,找到最佳值 + ``` + +#### 3.1.7 带宽限制 +- **功能**:人为限制测试使用的带宽 +- **格式**:数字+单位,如 `100M`、`1G` +- **单位**: + - K = Kbps(千比特每秒) + - M = Mbps(兆比特每秒) + - G = Gbps(千兆比特每秒) + +**为什么需要限制带宽?** +1. **避免网络拥塞**: + - 测试时不希望影响其他业务 + - 家庭中不影响家人上网 + - 企业中不影响生产系统 + +2. **模拟特定场景**: + - 测试在100M限制下的应用性能 + - 模拟低速链路(如移动网络) + - 验证QoS策略效果 + +3. **渐进式测试**: + - 从低带宽开始,逐步增加 + - 观察网络在不同负载下的表现 + +**应用示例**: +``` +场景1:家庭宽带是500M,但只想测试100M +设置:带宽限制 = 100M + +场景2:测试4K视频流所需带宽 +设置:带宽限制 = 25M (典型4K视频码率) + +场景3:模拟3G网络环境 +设置:带宽限制 = 5M (典型3G速度) +``` + +**专业技巧**: +1. **发现实际带宽**: + - 不设置限制,测试得到最大带宽 + - 然后设置为最大带宽的80%进行稳定性测试 + +2. **测试缓冲区影响**: + ``` + 步骤1:带宽限制 = 100M,测试 + 步骤2:带宽限制 = 200M,测试 + 步骤3:带宽限制 = 500M,测试 + 观察不同限制下的性能变化 + ``` + +3. **验证网络设备能力**: + - 设置接近设备标称值 + - 观察是否能稳定达到 + - 测试长时间稳定性 + +**注意事项**: +1. 实际限制可能受以下因素影响: + - 网络设备处理能力 + - 两端电脑性能 + - 其他网络流量 + +2. 如果设置限制但达不到: + - 可能是网络本身达不到该速度 + - 可能是其他瓶颈(如磁盘IO、CPU) + +3. 与"服务器比特率限制"的区别: + - 客户端限制:控制发送速率 + - 服务器限制:控制接收速率 + - 通常只需设置一端 + +#### 3.1.8 窗口大小 +- **技术名称**:TCP Window Size +- **作用**:控制"在途数据"的最大量 +- **单位**:字节,通常用K、M表示 +- **默认值**:系统自动调整 + +**通俗比喻**: +想象一个送货流程: +- 货物 = 数据包 +- 货车容量 = 窗口大小 +- 装满一车送一次 = 发送窗口数据 +- 更大的货车 = 更高的效率(在一定范围内) + +**详细解释**: +1. **什么是TCP窗口?** + TCP使用滑动窗口机制控制流量: + ``` + 发送方: [已确认][发送窗口][未发送] + ↑ + 窗口大小 + ``` + 窗口大小决定了一次可以发送多少数据而不需要等待确认。 + +2. **为什么重要?** + 公式:`最大吞吐量 = 窗口大小 / 往返时间(RTT)` + + 例子: + - RTT = 50ms(典型局域网) + - 窗口大小 = 64KB + - 最大吞吐量 = 64KB / 0.05s = 10.5Mbps + + 结论:对于高延迟网络,需要更大的窗口才能达到高速。 + +3. **如何选择合适的窗口大小?** + ``` + 公式:窗口大小 ≥ 带宽 × RTT + + 示例计算: + 带宽目标:1Gbps = 125MB/s + RTT:20ms = 0.02s + 所需窗口大小 = 125MB/s × 0.02s = 2.5MB + ``` + +**应用场景**: +1. **局域网测试**: + - RTT通常 < 1ms + - 默认窗口通常足够 + - 可以测试64K、128K、256K对比 + +2. **广域网测试**: + - RTT可能 > 50ms + - 需要增大窗口 + - 建议:1M、2M、4M、8M 测试 + +3. **互联网测试**: + - RTT可能 > 100ms + - 窗口需要更大 + - 建议:2M、4M、8M、16M + +**设置建议**: +``` +网络类型 典型RTT 建议窗口大小 +局域网 <1ms 64K-256K +城域网 5-20ms 512K-2M +国内跨省 30-80ms 2M-8M +国际链路 100-300ms 8M-32M +卫星链路 >500ms >64M +``` + +**专业调试步骤**: +1. 不设置窗口(使用默认),测试得到基准 +2. 逐步增大窗口,观察吞吐量变化: + ``` + 测试1:窗口 = 64K + 测试2:窗口 = 128K + 测试3:窗口 = 256K + 测试4:窗口 = 512K + ... + 直到吞吐量不再增加 + ``` +3. 记录最佳窗口值 + +**注意事项**: +1. **窗口不是越大越好**: + - 过大窗口可能导致拥塞 + - 消耗更多内存 + - 丢包时重传更多数据 + +2. **需要考虑接收方窗口**: + TCP通信中,实际窗口 = min(发送方窗口, 接收方窗口) + 两端都需要适当设置。 + +3. **与MSS的关系**: + - MSS是单个包的大小 + - 窗口是多个包的总量 + - 通常:窗口大小是MSS的整数倍 + +**实际案例**: +案例:公司总部(北京)到分公司(上海)专线 +- 带宽:100Mbps +- 测量RTT:35ms +- 计算理想窗口:100Mbps × 0.035s ≈ 3.5Mbits = 437KB +- 测试设置:从256K开始,逐步增加到1M、2M、4M +- 结果:2M窗口时达到最佳性能 + +#### 3.1.9 传输数据量 +- **替代选项**:与"测试时间"二选一 +- **格式**:数字+单位,如 `100M`、`1G` +- **单位**: + - K = KB(千字节) + - M = MB(兆字节) + - G = GB(千兆字节) + +**与"测试时间"的区别**: +- 测试时间:固定时长,看能传多少数据 +- 传输数据量:固定数据量,看需要多少时间 + +**适用场景**: +1. **测试特定文件传输**: + - 模拟传输1GB文件需要的时间 + - 预估大文件传输耗时 + +2. **短时突发测试**: + - 只传输100MB数据 + - 快速测试,避免长时间占用网络 + +3. **一致性测试**: + - 每次都传输相同数据量 + - 比较不同时间/配置下的性能 + +**示例**: +``` +场景:测试备份1TB数据到云存储的时间 +设置:传输数据量 = 1G (先用小量测试) +结果:传输1G需要30秒 +推算:1TB ≈ 1000 × 30秒 = 8.3小时 +``` + +#### 3.1.10 块数量 +- **作用**:指定传输的块(block)数量 +- **单位**:个 +- **适用**:UDP测试或特定测试场景 + +**技术细节**: +- 每个块包含多个数据包 +- 对于UDP,可以控制发送的数据包数量 +- 对于TCP,较少使用此参数 + +**应用场景**: +1. **UDP包数量测试**: + - 发送10000个UDP包 + - 统计丢包率 + - 测试网络设备包转发能力 + +2. **特定协议模拟**: + - 模拟VoIP通话(每秒50个包) + - 模拟传感器数据(每秒10个包) + +#### 3.1.11 缓冲区长度 +- **作用**:控制读写缓冲区大小 +- **单位**:字节,通常用K表示 +- **默认**:系统默认(通常8K或64K) + +**缓冲区的作用**: +``` +应用程序 → 应用缓冲区 → TCP栈 → 网络 +接收方:网络 → TCP栈 → 应用缓冲区 → 应用程序 +``` + +**设置建议**: +1. **常规测试**:使用默认值 +2. **高性能网络**:增大缓冲区(如64K、128K) +3. **高延迟网络**:需要更大缓冲区 + +**缓冲区与窗口的关系**: +- 缓冲区:在内存中暂存数据 +- 窗口:在网络中在途数据 +- 缓冲区 ≥ 窗口 才能充分发挥性能 + +#### 3.1.12 报告间隔 +- **作用**:控制结果输出的频率 +- **单位**:秒 +- **范围**:0.1-10.0秒 +- **默认**:1.0秒 + +**报告内容**: +每间隔时间输出一次统计,包括: +- 时间区间 +- 传输数据量 +- 带宽 +- (UDP)抖动和丢包 + +**设置策略**: +1. **详细监控**:0.1-0.5秒 + - 观察瞬时波动 + - 调试网络问题 + - 缺点:输出信息多 + +2. **标准测试**:1.0秒(默认) + - 平衡详细度和可读性 + - 适合大多数场景 + +3. **长时间测试**:2.0-5.0秒 + - 减少输出信息 + - 观察趋势变化 + +**输出示例**: +``` +[ ID] Interval Transfer Bandwidth +[ 5] 0.00-1.00 sec 117 MBytes 982 Mbits/sec +[ 5] 1.00-2.00 sec 118 MBytes 989 Mbits/sec +[ 5] 2.00-3.00 sec 119 MBytes 998 Mbits/sec +``` + +#### 3.1.13 单位格式 +- **作用**:控制结果显示的单位 +- **选项**:自动、K、M、G、T +- **默认**:自动(根据数值自动选择) + +**各单位的含义**: +- K = Kbits/sec 或 KBytes/sec +- M = Mbits/sec 或 MBytes/sec +- G = Gbits/sec 或 GBytes/sec +- T = Tbits/sec 或 TBytes/sec + +**选择建议**: +1. **自动**:让程序根据数值大小自动选择 +2. **固定单位**:强制使用特定单位,便于比较 + +**示例**: +``` +实际值:952 Mbits/sec +显示为: +- 自动:952 Mbits/sec +- 强制K:975,000 Kbits/sec +- 强制G:0.95 Gbits/sec +``` + +#### 31.14 MSS(最大段大小) +- **全称**:Maximum Segment Size +- **作用**:控制TCP数据包的有效载荷大小 +- **单位**:字节 +- **默认**:1460(以太网标准) + +**通俗解释**: +MSS就是TCP数据包中实际数据的最大大小(不包括TCP头部和IP头部)。 + +**详细说明**: +``` +完整数据包结构: +[以太网头][IP头][TCP头][数据][以太网尾] + ↑ + MSS +典型值:1500(MTU) - 20(IP头) - 20(TCP头) = 1460 +``` + +**为什么需要调整MSS?** +1. **网络MTU限制**: + - 某些网络MTU不是1500(如PPPoE是1492) + - 需要相应减小MSS + - 公式:MSS = MTU - 40(IP头20+TCP头20) + +2. **避免分片**: + - 数据包过大可能被分片 + - 分片降低性能,增加丢包风险 + - 适当MSS可避免分片 + +3. **优化性能**: + - 某些场景下特定MSS可能更优 + - 需要实验测试 + +**常见MTU/MSS组合**: +``` +网络类型 MTU 建议MSS +标准以太网 1500 1460 +PPPoE 1492 1452 +Jumbo Frame 9000 8960 +VPN隧道 1400-1420 对应减少 +``` + +**设置建议**: +1. **一般情况**:保持默认0(使用系统默认) +2. **遇到问题时**: + - 测试标准MSS:1460 + - 测试PPPoE MSS:1452 + - 测试小包:536(最小安全值) + +3. **诊断方法**: + ``` + 步骤1:ping测试MTU + ping -l 1472 -f 目标IP + 如果不通,逐步减小直到通 + + 步骤2:计算MSS + MSS = 成功值 + 28 - 40 + + 步骤3:在iperf中设置该MSS + ``` + +**专业应用**: +1. **VPN环境**: + - VPN增加额外头部 + - 需要减小MSS + - 通常设置为1350-1400 + +2. **广域网优化**: + - 某些设备对特定MSS有优化 + - 需要实验确定最佳值 + +3. **TCP性能调优**: + - MSS影响窗口缩放 + - 影响重传效率 + - 专业调优参数 + +**注意事项**: +1. **两端需要匹配**: + TCP连接使用双方较小的MSS值 + 需要两端都适当设置 + +2. **不是越大越好**: + 过大MSS可能导致: + - 分片 + - 增加延迟 + - 增加丢包影响 + +3. **与窗口关系**: + 窗口大小应该是MSS的整数倍 + 否则会有部分浪费 + +### 3.2 "高级选项"标签页 +包含更多专业选项,适合高级用户和特定场景。 + +#### 3.2.1 客户端高级选项 + +##### 连接超时 +- **作用**:设置建立连接的最大等待时间 +- **单位**:毫秒(ms) +- **默认**:0(使用系统默认,通常30-60秒) + +**适用场景**: +1. **快速失败**:网络不通时快速返回错误 +2. **严格测试**:要求连接必须在指定时间内建立 +3. **自动化测试**:避免长时间等待 + +**设置建议**: +``` +网络类型 建议超时 +局域网 1000-5000 ms +广域网 5000-30000 ms +高延迟网络 30000-60000 ms +移动网络 10000-30000 ms +``` + +##### 绑定设备 +- **作用**:指定使用哪个网络接口 +- **格式**:接口名称 +- **示例**:`eth0`、`wlan0`、`en0`、`以太网`、`Wi-Fi` + +**为什么需要绑定设备?** +1. **多网卡选择**:电脑有多个网卡时 +2. **指定路径**:强制使用有线或无线 +3. **测试特定接口**:测试某个网卡性能 + +**查看设备名称**: +``` +Windows: ipconfig /all +Linux: ip addr 或 ifconfig +macOS: ifconfig 或 networksetup -listallhardwareports +``` + +##### 绑定主机 +- **作用**:指定源IP地址 +- **格式**:IP地址 +- **用途**: + 1. 多IP主机指定源地址 + 2. VPN环境指定出口 + 3. 测试特定源地址的路由 + +##### 客户端端口 +- **作用**:指定客户端使用的端口号 +- **格式**:端口号或范围 +- **示例**: + - `60000`:固定端口 + - `60000-60010`:端口范围 + +**应用场景**: +1. **防火墙规则**:只允许特定端口 +2. **NAT穿透**:配合端口转发 +3. **多客户端识别**:不同客户端用不同端口 + +##### 省略时间 +- **作用**:跳过测试开始的一段时间 +- **单位**:秒 +- **默认**:0(不省略) + +**为什么需要省略?** +TCP需要时间达到稳定状态: +1. **慢启动**:TCP从低速逐渐增加 +2. **缓冲区填充**:需要时间填满管道 +3. **避免初始波动影响结果** + +**建议值**: +- 短测试(10秒):省略2秒 +- 标准测试(60秒):省略5秒 +- 长测试(300秒+):省略10秒 + +##### 标题 +- **作用**:为输出行添加前缀 +- **用途**: + 1. 区分多个同时运行的测试 + 2. 记录测试信息 + 3. 自动化测试标签 + +**示例**: +``` +设置标题:办公室到机房 +输出:[办公室到机房] [ 5] 0.00-1.00 sec 117 MBytes 982 Mbits/sec +``` + +##### 额外数据 +- **作用**:在JSON输出中包含自定义数据 +- **格式**:字符串 +- **用途**:记录测试环境信息 + +**示例**: +``` +额外数据:location=beijing;device=routerA;test_id=20231201_001 +``` + +#### 3.2.2 网络选项 + +##### IP版本 +- **选项**:自动、仅IPv4、仅IPv6 +- **默认**:自动 + +**选择策略**: +1. **自动**:让系统自动选择(推荐) +2. **仅IPv4**:强制使用IPv4 +3. **仅IPv6**:强制使用IPv6 + +**应用场景**: +- IPv6测试:选择仅IPv6 +- 兼容性测试:分别测试IPv4和IPv6 +- 问题诊断:确定是IPv4还是IPv6的问题 + +##### TOS(服务类型) +- **作用**:设置IP包的服务类型字段 +- **范围**:0-255 +- **默认**:0 + +**常见TOS值**: +``` +0x00 (0): 一般服务 +0x10 (16): 最小延迟(如SSH、Telnet) +0x08 (8): 最大吞吐量(如FTP) +0x04 (4): 最高可靠性 +0x02 (2): 最小成本 +``` + +**实际应用**: +1. **测试QoS**:验证不同TOS值的优先级 +2. **模拟应用**:模拟VoIP(最小延迟)或FTP(最大吞吐量) +3. **网络调优**:测试网络设备对TOS的处理 + +##### DSCP(差分服务代码点) +- **作用**:更精细的QoS标记 +- **范围**:0-63 +- **默认**:0 + +**常见DCSD值**: +``` +CS0 (0): 默认 +EF (46): 加速转发(语音) +AF41 (34): 保证转发(视频) +AF31 (26): 保证转发(语音信令) +AF21 (18): 保证转发(交互式) +AF11 (10): 保证转发(批量数据) +``` + +#### 3.2.3 性能选项 + +##### 定时器 +- **作用**:控制数据发送的节奏 +- **单位**:微秒(μs) +- **默认**:根据带宽自动计算 + +**技术原理**: +定时器控制发送数据包的时间间隔: +- 值越小:发送越密集,可能突发 +- 值越大:发送越平稳,更均匀 + +**计算公式**: +``` +定时器 ≈ 包大小 / 目标带宽 +示例:目标1Gbps,包1500字节 +定时器 ≈ 1500×8 bits / 1e9 bps ≈ 12 μs +``` + +##### 接收超时 +- **作用**:设置接收数据的超时时间 +- **单位**:毫秒(ms) +- **默认**:0(不超时) + +**应用场景**: +1. **不稳定网络**:网络频繁中断 +2. **移动网络**:信号可能丢失 +3. **严格测试**:要求持续稳定传输 + +#### 3.2.4 选项复选框 + +##### 反向测试 +- **作用**:交换发送和接收方向 +- **命令**:`-R` + +**通俗解释**: +正常情况下:客户端发送,服务器接收 +反向测试:服务器发送,客户端接收 + +**应用场景**: +1. **测试上行带宽**:从服务器到客户端 +2. **非对称链路测试**:如ADSL(上行小,下行大) +3. **双向测试准备**:先测A→B,再测B→A + +##### 双向测试 +- **作用**:同时进行双向传输 +- **命令**:`--bidir` + +**与反向测试的区别**: +- 反向测试:单向,但方向相反 +- 双向测试:同时两个方向 + +**应用场景**: +1. **全双工测试**:测试设备同时收发能力 +2. **实际应用模拟**:如视频会议(双方都在发视频) +3. **网络压力测试**:双向满负载 + +##### 禁用Nagle算法 +- **作用**:关闭TCP的Nagle算法 +- **命令**:`-N` + +**Nagle算法是什么?** +- 目的:减少小包数量 +- 原理:积累小数据,合并发送 +- 优点:减少包数量,提高效率 +- 缺点:增加延迟 + +**什么时候禁用?** +1. **实时应用测试**:如游戏、VoIP +2. **低延迟需求**:需要最小化延迟 +3. **交互式应用**:如Telnet、SSH + +**注意**:禁用Nagle可能增加包数量,降低效率。 + +##### 不分片(DF标志) +- **作用**:设置IP包的Don't Fragment标志 +- **命令**:`--dont-fragment` + +**DF标志的作用**: +- 设置后:路由器不能分片此包 +- 如果包太大:路由器丢弃并返回错误 +- 用途:发现路径MTU + +**应用场景**: +1. **MTU发现**:配合ping使用 +2. **避免分片**:分片降低性能,增加丢包 +3. **特定测试**:测试网络对不分片包的处理 + +##### 零拷贝 +- **作用**:使用零拷贝技术发送数据 +- **命令**:`-Z` + +**零拷贝技术**: +- 传统:数据从用户空间→内核空间→网卡 +- 零拷贝:数据直接从用户空间→网卡 +- 优点:减少CPU使用,提高性能 +- 要求:系统支持,特定网卡驱动 + +**适用场景**: +1. **高性能测试**:10G+网络 +2. **CPU受限环境**:CPU性能是瓶颈 +3. **专业评估**:测试零拷贝效果 + +##### 跳过接收拷贝 +- **作用**:在接收端使用零拷贝 +- **命令**:`--skip-rx-copy` + +**注意事项**: +1. 需要两端都支持 +2. 可能不稳定 +3. 主要用于测试和开发 + +##### UDP 64位计数器 +- **作用**:使用64位统计计数器(UDP) +- **命令**:`--udp-counters-64bit` + +**为什么需要?** +- 32位计数器最大4GB +- 高速长时间测试可能溢出 +- 64位支持更大计数 + +##### 重复负载 +- **作用**:UDP负载使用重复模式 +- **命令**:`--repeating-payload` + +**用途**: +1. **压缩测试**:测试网络设备的压缩能力 +2. **模式识别**:测试DPI设备识别能力 +3. **特定测试**:某些测试场景需要 + +##### 获取服务器输出 +- **作用**:客户端获取服务器端的输出 +- **命令**:`--get-server-output` + +**应用场景**: +1. **集中监控**:客户端查看两端结果 +2. **自动化测试**:一次获取所有数据 +3. **对比分析**:比较客户端和服务器视角 + +##### 单次连接 +- **作用**:服务器处理一个连接后退出 +- **命令**:`-1` + +**应用场景**: +1. **自动化脚本**:测试完自动退出 +2. **临时测试**:只测一次 +3. **资源清理**:避免忘记停止服务器 + +##### 守护进程模式 +- **作用**:服务器作为守护进程运行 +- **命令**:`-D` + +**特点**: +- 后台运行 +- 输出到系统日志 +- 适合长期运行 + +##### 使用PKCS1填充 +- **作用**:RSA加密使用PKCS1填充 +- **命令**:`--use-pkcs1-padding` + +**安全相关**: +- 默认使用OAEP填充(更安全) +- PKCS1用于兼容旧系统 +- 除非必要,否则使用默认 + +### 3.3 "服务器选项"标签页 + +#### 3.3.1 服务器限制 + +##### 服务器比特率限制 +- **作用**:限制服务器的发送速率 +- **格式**:如 `100M`、`1G` +- **与客户端限制的区别**: + - 客户端限制:控制发送速率 + - 服务器限制:控制接收速率(在反向测试中是发送速率) + +**应用场景**: +1. **限制服务器负载**:保护服务器不被压垮 +2. **模拟低性能服务器**:测试客户端在低速服务器下的表现 +3. **非对称测试**:模拟上行带宽小的服务器 + +##### 空闲超时 +- **作用**:无数据时自动断开连接的时间 +- **单位**:秒 +- **默认**:0(不超时) + +**用途**: +1. **资源清理**:自动断开空闲连接 +2. **安全考虑**:避免连接一直开放 +3. **自动化管理**:无需手动清理 + +**设置建议**: +``` +测试场景 建议超时 +临时测试 60-300秒 +长期运行 3600秒(1小时) +公开服务器 1800秒(30分钟) +``` + +##### 服务器最大持续时间 +- **作用**:服务器运行的最长时间 +- **单位**:秒 +- **默认**:0(无限制) + +**应用场景**: +1. **定时测试**:每天运行2小时 +2. **活动期间**:会议期间限时开放 +3. **资源控制**:避免长期占用 + +##### 时间偏差阈值 +- **作用**:允许的客户端服务器时间差 +- **单位**:秒 +- **默认**:1.0秒 + +**用途**: +- 时间同步检查 +- 防止时间不同步导致的统计错误 +- 安全考虑 + +#### 3.3.2 认证选项 + +##### 用户名 +- **作用**:客户端认证用户名 +- **需要配合**:服务器端用户列表 + +##### RSA私钥路径 +- **作用**:服务器私钥文件路径 +- **格式**:文件路径 +- **用途**:加密通信 + +##### RSA公钥路径 +- **作用**:客户端公钥文件路径 +- **用途**:验证服务器 + +##### 授权用户路径 +- **作用**:授权用户配置文件路径 +- **格式**:JSON或文本文件 + +**示例用户文件**: +```json +{ + "users": [ + { + "username": "testuser", + "password_hash": "..." + } + ] +} +``` + +#### 3.3.3 文件选项 + +##### 文件传输 +- **作用**:发送指定文件内容 +- **命令**:`-F 文件名` + +**特点**: +- 发送文件内容作为测试数据 +- 不实际传输文件 +- 用于特定模式测试 + +##### PID文件 +- **作用**:将进程ID写入文件 +- **用途**: + - 方便管理 + - 自动化脚本控制 + - 监控进程状态 + +##### 日志文件 +- **作用**:将输出写入文件 +- **用途**: + - 长期记录 + - 后续分析 + - 审计追踪 + +#### 3.3.4 系统选项 + +##### CPU亲和性 +- **作用**:绑定到特定CPU核心 +- **格式**:CPU编号,如 `0`、`0,1` + +**应用场景**: +1. **性能测试**:避免CPU迁移影响 +2. **多核优化**:绑定到特定核心 +3. **NUMA系统**:优化内存访问 + +##### 时间戳格式 +- **作用**:自定义时间戳格式 +- **格式**:strftime格式 +- **示例**:`%H:%M:%S`、`%Y-%m-%d %H:%M:%S` + +#### 3.3.5 输出选项 + +##### JSON输出 +- **作用**:以JSON格式输出结果 +- **用途**: + - 程序解析 + - 自动化处理 + - 数据收集 + +##### JSON流输出 +- **作用**:实时JSON流输出 +- **特点**: + - 每间隔输出一次JSON + - 实时监控 + - 流式处理 + +##### 完整JSON流输出 +- **作用**:包含更多详细信息的JSON流 + +##### 详细输出 +- **作用**:显示更多详细信息 +- **用途**:调试、详细分析 + +##### 显示版本 +- **作用**:显示iperf3版本信息 + +##### 调试模式 +- **作用**:启用调试输出 +- **级别**:1-4,数字越大越详细 + +##### 强制刷新输出 +- **作用**:立即刷新输出缓冲区 +- **用途**:实时查看输出 + +##### 时间戳 +- **作用**:每行输出添加时间戳 +- **用途**:精确时间记录 + +### 3.4 "测试结果"标签页 +显示测试结果和统计信息。 + +#### 结果文本区域 +- **显示内容**:iperf3原始输出 +- **功能**: + - 实时更新 + - 彩色显示(如果支持) + - 自动滚动 + +#### 统计信息区域 +显示关键指标: +1. **带宽**:测试期间的平均带宽 +2. **抖动**:UDP测试的延迟变化 +3. **丢包**:UDP测试的丢包率 +4. **时间**:测试持续时间 +5. **数据量**:传输的总数据量 +6. **包数量**:发送/接收的包数 +7. **重传**:TCP重传次数 +8. **发送者**:发送端统计 +9. **接收者**:接收端统计 + +### 3.5 "历史记录"标签页 +管理历次测试记录。 + +#### 表格功能 +- **列**:时间、模式、协议、服务器、带宽、抖动、丢包、持续时间、并行流、备注 +- **排序**:点击列标题排序 +- **查看**:双击查看详情 + +#### 操作按钮 +1. **清空历史**:删除所有记录 +2. **导出记录**:保存为CSV文件 +3. **加载历史**:从文件加载历史记录 +4. **保存结果**:保存当前测试结果 + +--- + +## 第四章:实用测试方案 + +### 4.1 家庭网络测试方案 + +#### 4.1.1 基础速度测试 +**目的**:了解家庭宽带实际速度 + +**步骤**: +1. **本地回环测试**(验证工具) + - 模式:客户端 + - 服务器:127.0.0.1 + - 时间:10秒 + - 结果应该接近硬件极限(>1Gbps) + +2. **局域网测试**(排除互联网因素) + - 用另一台电脑作为服务器 + - 测试有线连接(>900Mbps为正常) + - 测试Wi-Fi连接(根据规格,如Wi-Fi6应>600Mbps) + +3. **互联网速度测试** + - 使用公共iperf3服务器(如 ping.online.net) + - 或自己在外网搭建服务器 + - 与运营商宣称速度对比 + +**结果解读**: +- 有线局域网:应接近1000Mbps +- Wi-Fi 5:200-500Mbps +- Wi-Fi 6:400-800Mbps +- 家庭宽带:通常是标称的80-90% + +#### 4.1.2 Wi-Fi信号强度测试 +**目的**:找到最佳Wi-Fi位置 + +**方法**: +1. 服务器放在路由器旁(有线连接) +2. 客户端在不同位置测试 +3. 记录各位置的速度 + +**测试点**: +- 同一房间 +- 隔一堵墙 +- 隔两堵墙 +- 楼上/楼下 +- 最远角落 + +#### 4.1.3 多设备并发测试 +**目的**:测试多人同时使用时的网络情况 + +**方法**: +1. 设置并行流:4-8 +2. 模拟场景:一人看4K视频(25Mbps)+一人游戏(10Mbps)+一人下载 +3. 观察总带宽和每个流的稳定性 + +### 4.2 企业网络测试方案 + +#### 4.2.1 网络验收测试 +**新网络部署后验证**: + +**测试项目**: +1. **单向带宽测试**: + - 每个链路单独测试 + - 使用标准参数 + - 记录基准值 + +2. **双向带宽测试**: + - 测试全双工性能 + - 验证交换机性能 + +3. **多流并发测试**: + - 测试设备并发处理能力 + - 模拟多用户场景 + +4. **长时间稳定性测试**: + - 持续测试30分钟 + - 检查是否有波动 + +**验收标准**: +- 达到合同规定带宽的95%以上 +- 丢包率<0.1% +- 抖动<5ms(对于实时应用) + +#### 4.2.2 故障诊断测试 +**网络变慢时排查**: + +**排查步骤**: +1. **分层测试法**: + ``` + 第一步:本地回环 → 正常?继续,否则本地问题 + 第二步:同交换机 → 正常?继续,否则交换机问题 + 第三步:跨交换机 → 正常?继续,否则互联问题 + 第四步:跨路由器 → 正常?继续,否则路由问题 + 第五步:互联网 → 分析结果 + ``` + +2. **对比测试法**: + - 同时测试两条相似链路 + - 对比结果找差异 + +3. **时间分段测试**: + - 不同时间段测试 + - 找出规律(如每天特定时间慢) + +#### 4.2.3 容量规划测试 +**为扩容提供依据**: + +**收集数据**: +1. **当前使用率**: + - 业务高峰时测试 + - 记录实际使用带宽 + +2. **增长趋势**: + - 每月测试一次 + - 分析增长曲线 + +3. **应用需求**: + - 测试关键应用所需带宽 + - 如视频会议、文件同步等 + +**规划建议**: +- 当前使用率 > 70%:开始规划扩容 +- 当前使用率 > 85%:紧急扩容 +- 考虑20-30%的冗余 + +### 4.3 云服务测试方案 + +#### 4.3.1 云服务器网络性能测试 +**测试不同云厂商/区域的性能**: + +**测试矩阵**: +``` +维度: +1. 云厂商:AWS、Azure、GCP、阿里云、腾讯云等 +2. 区域:不同地理区域 +3. 实例类型:不同规格的虚拟机 +4. 网络类型:普通网络、增强网络 +``` + +**测试方法**: +1. **同区域测试**:同一数据中心内 +2. **跨区域测试**:不同数据中心之间 +3. **跨云测试**:不同云厂商之间 +4. **到用户测试**:从云到实际用户位置 + +#### 4.3.2 网络类型对比测试 +**测试不同类型的云网络**: + +**测试项目**: +1. **普通网络 vs 增强网络**: + - 延迟对比 + - 带宽对比 + - 稳定性对比 + +2. **公网 vs 内网**: + - 安全组影响 + - 带宽限制差异 + - 成本差异 + +3. **不同带宽包测试**: + - 按量计费 + - 包年包月 + - 共享带宽 + +### 4.4 特殊场景测试方案 + +#### 4.4.1 VPN/专线测试 +**测试加密隧道性能**: + +**测试重点**: +1. **加密开销**: + - 测试VPN开启前后的差异 + - 计算加密带来的性能损失 + +2. **MTU/MSS调整**: + - 测试不同MSS值 + - 找到最佳值 + +3. **稳定性测试**: + - 长时间测试(24小时) + - 检查是否有断线 + +#### 4.4.2 移动网络测试 +**测试4G/5G网络性能**: + +**特点**: +- 波动较大 +- 受信号强度影响 +- 有数据限制 + +**测试建议**: +1. **多点测试**:不同地理位置 +2. **多时段测试**:早中晚不同时间 +3. **移动中测试**:移动过程中的变化 + +#### 4.4.3 物联网网络测试 +**测试低功耗网络**: + +**测试类型**: +1. **NB-IoT/LoRa测试**: + - 低带宽测试(几Kbps) + - 高延迟测试(几秒) + - 功耗间接测试 + +2. **连接稳定性**: + - 测试重连机制 + - 测试弱信号处理 + +--- + +## 第五章:结果分析与问题诊断 + +### 5.1 结果解读指南 + +#### 5.1.1 TCP测试结果解读 +**正常输出示例**: +``` +[ ID] Interval Transfer Bandwidth Retr +[ 5] 0.00-10.00 sec 1.10 GBytes 944 Mbits/sec 0 +[ 5] 10.00-20.00 sec 1.15 GBytes 987 Mbits/sec 1 +[ 5] 20.00-30.00 sec 1.12 GBytes 962 Mbits/sec 0 +[ 5] 30.00-40.00 sec 1.14 GBytes 979 Mbits/sec 0 +[ 5] 40.00-50.00 sec 1.13 GBytes 971 Mbits/sec 2 +``` + +**关键指标**: +1. **带宽**:944-987 Mbits/sec(波动约5%,正常) +2. **重传**:0-2次(很少,网络质量好) +3. **稳定性**:各时间段结果接近 + +#### 5.1.2 UDP测试结果解读 +**正常输出示例**: +``` +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 5] 0.00-10.00 sec 128 MBytes 107 Mbits/sec 0.512 ms 0/10000 (0%) +[ 5] 10.00-20.00 sec 129 MBytes 108 Mbits/sec 0.498 ms 1/10001 (0.01%) +[ 5] 20.00-30.00 sec 127 MBytes 107 Mbits/sec 0.523 ms 0/10000 (0%) +``` + +**关键指标**: +1. **带宽**:稳定在107-108 Mbits/sec +2. **抖动**:0.5ms左右(优秀) +3. **丢包**:0-0.01%(优秀) + +### 5.2 常见问题诊断 + +#### 5.2.1 速度达不到预期 + +**可能原因及排查**: +1. **硬件限制**: + - 检查网卡规格(百兆/千兆/万兆) + - 检查路由器/交换机规格 + - 检查网线质量(CAT5e以上) + +2. **软件限制**: + - 检查操作系统网络设置 + - 检查防火墙/安全软件 + - 检查TCP参数(窗口大小等) + +3. **网络问题**: + - 使用ping测试延迟和丢包 + - 使用traceroute查看路径 + - 检查是否有带宽限制策略 + +**排查步骤**: +``` +步骤1:测试本地回环 → 排除本机问题 +步骤2:测试同交换机 → 排除交换机问题 +步骤3:测试跨设备 → 定位问题设备 +步骤4:分段测试 → 找到瓶颈段 +``` + +#### 5.2.2 测试结果波动大 + +**可能原因**: +1. **网络拥塞**: + - 其他应用占用带宽 + - 网络设备队列拥塞 + - 广播风暴等异常 + +2. **无线网络问题**: + - 信号干扰 + - 信号衰减 + - 信道冲突 + +3. **设备性能问题**: + - CPU/内存不足 + - 磁盘IO瓶颈 + - 网卡驱动问题 + +**解决方法**: +1. **隔离测试**:关闭其他应用 +2. **多次测试**:取平均值 +3. **分段测试**:确定波动来源 + +#### 5.2.3 连接失败 + +**错误排查**: +1. **"连接被拒绝"**: + - 服务器未运行 + - 端口错误 + - 防火墙阻挡 + +2. **"连接超时"**: + - 网络不通 + - 路由问题 + - 防火墙丢弃 + +3. **"地址无法解析"**: + - 域名错误 + - DNS问题 + - 本地hosts文件问题 + +**检查清单**: +``` +□ 服务器是否运行? +□ 端口是否正确? +□ 防火墙是否允许? +□ 网络是否连通? +□ 地址是否正确? +``` + +### 5.3 性能优化建议 + +#### 5.3.1 针对高延迟网络 +**优化措施**: +1. **增大TCP窗口**: + ``` + 公式:窗口大小 ≥ 带宽 × RTT + 示例:100Mbps带宽,100ms RTT + 窗口 ≥ 100Mbps × 0.1s = 10Mbits = 1.25MB + ``` + +2. **启用窗口缩放**: + - 现代TCP自动支持 + - 确保两端都支持 + +3. **调整TCP算法**: + - 尝试不同拥塞控制算法 + - 如BBR、CUBIC等 + +#### 5.3.2 针对高丢包网络 +**优化措施**: +1. **减小MSS**: + - 大包更容易被丢弃 + - 尝试536-1024的小包 + +2. **启用SACK**: + - 选择性确认 + - 提高重传效率 + +3. **调整重传策略**: + - 减少快速重传阈值 + - 调整RTO参数 + +#### 5.3.3 针对无线网络 +**优化措施**: +1. **使用UDP测试**: + - TCP对无线不友好 + - UDP更能反映真实性能 + +2. **调整包大小**: + - 无线有额外开销 + - 找到最佳包大小 + +3. **考虑无线特性**: + - 信号强度影响 + - 干扰避免 + - MIMO利用 + +--- + +## 第六章:高级应用与自动化 + +### 6.1 自动化测试脚本 + +#### 6.1.1 Python自动化示例 +```python +import subprocess +import json +import time +from datetime import datetime + +def run_iperf_test(config): + """运行iperf测试""" + cmd = ["iperf3", "-c", config["server"], "-t", str(config["duration"])] + + if config.get("parallel"): + cmd.extend(["-P", str(config["parallel"])]) + + if config.get("bandwidth"): + cmd.extend(["-b", config["bandwidth"]]) + + # 运行测试 + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=config["duration"] + 10 + ) + + return parse_iperf_output(result.stdout) + +def parse_iperf_output(output): + """解析iperf输出""" + lines = output.split('\n') + results = { + "bandwidth": 0, + "jitter": 0, + "loss": 0, + "timestamp": datetime.now().isoformat() + } + + for line in lines: + if "bits/sec" in line and "sender" in line: + # 解析带宽 + if "Gbits/sec" in line: + match = re.search(r'([\d\.]+)\s+Gbits/sec', line) + if match: + results["bandwidth"] = float(match.group(1)) * 1000 + elif "Mbits/sec" in line: + # ... 类似处理 + + # 解析其他指标... + + return results + +def main(): + # 测试配置 + tests = [ + {"server": "192.168.1.100", "duration": 30, "parallel": 1}, + {"server": "192.168.1.100", "duration": 30, "parallel": 4}, + {"server": "192.168.1.100", "duration": 30, "parallel": 8}, + ] + + all_results = [] + for test_config in tests: + print(f"运行测试: {test_config}") + result = run_iperf_test(test_config) + all_results.append(result) + time.sleep(5) # 测试间隔 + + # 保存结果 + with open("test_results.json", "w") as f: + json.dump(all_results, f, indent=2) + + print("测试完成,结果已保存") + +if __name__ == "__main__": + main() +``` + +#### 6.1.2 定期监控脚本 +```python +#!/usr/bin/env python3 +""" +网络质量定期监控脚本 +每天定时测试并记录 +""" + +import schedule +import time +from iperf_automation import run_iperf_test + +def daily_monitor(): + """每日监控任务""" + print(f"开始每日网络监控 - {time.ctime()}") + + # 测试到多个目标 + targets = [ + {"name": "本地服务器", "server": "192.168.1.1", "port": 5201}, + {"name": "互联网测试点1", "server": "ping.online.net", "port": 5201}, + {"name": "互联网测试点2", "server": "iperf.he.net", "port": 5201}, + ] + + results = [] + for target in targets: + try: + result = run_iperf_test({ + "server": target["server"], + "duration": 60, + "parallel": 4 + }) + result["target"] = target["name"] + results.append(result) + except Exception as e: + print(f"测试{target['name']}失败: {e}") + + # 保存结果 + save_results(results) + print("每日监控完成") + +def save_results(results): + """保存结果到数据库或文件""" + # 这里可以保存到数据库、文件或发送到监控系统 + pass + +# 设置定时任务 +schedule.every().day.at("02:00").do(daily_monitor) # 每天凌晨2点 +schedule.every().hour.do(lambda: run_quick_test()) # 每小时快速测试 + +def run_quick_test(): + """快速测试""" + pass + +if __name__ == "__main__": + print("网络监控服务启动...") + while True: + schedule.run_pending() + time.sleep(60) +``` + +### 6.2 与监控系统集成 + +#### 6.2.1 Prometheus集成 +```python +from prometheus_client import start_http_server, Gauge +import time + +# 创建指标 +BANDWIDTH_GAUGE = Gauge('network_bandwidth_mbps', + 'Network bandwidth in Mbps', + ['direction', 'server']) +LATENCY_GAUGE = Gauge('network_latency_ms', + 'Network latency in ms', + ['server']) +LOSS_GAUGE = Gauge('network_packet_loss_percent', + 'Packet loss percentage', + ['server']) + +def update_metrics(server, results): + """更新Prometheus指标""" + BANDWIDTH_GAUGE.labels(direction='upload', server=server).set( + results.get('upload_bandwidth', 0) + ) + BANDWIDTH_GAUGE.labels(direction='download', server=server).set( + results.get('download_bandwidth', 0) + ) + LATENCY_GAUGE.labels(server=server).set( + results.get('latency', 0) + ) + LOSS_GAUGE.labels(server=server).set( + results.get('loss', 0) + ) + +def monitoring_loop(): + """监控循环""" + start_http_server(8000) # Prometheus metrics端口 + + servers = ["server1", "server2", "server3"] + + while True: + for server in servers: + try: + # 运行iperf测试 + results = run_iperf_test_to(server) + + # 更新指标 + update_metrics(server, results) + + except Exception as e: + print(f"监控{server}失败: {e}") + + time.sleep(300) # 每5分钟一次 +``` + +#### 6.2.2 Grafana仪表板 +创建监控仪表板,包含: +1. **实时带宽图表** +2. **历史趋势图** +3. **网络质量评分** +4. **告警面板** +5. **地理分布图** + +### 6.3 批量测试与报告生成 + +#### 6.3.1 批量测试框架 +```python +class BatchTester: + def __init__(self, config_file): + self.configs = self.load_configs(config_file) + self.results = [] + + def load_configs(self, config_file): + """加载测试配置""" + # 从JSON/YAML文件加载 + pass + + def run_all_tests(self): + """运行所有测试""" + for test_name, config in self.configs.items(): + print(f"运行测试: {test_name}") + + try: + result = self.run_single_test(config) + result["test_name"] = test_name + result["timestamp"] = datetime.now().isoformat() + + self.results.append(result) + + # 可选:测试间等待 + time.sleep(config.get("interval", 10)) + + except Exception as e: + print(f"测试{test_name}失败: {e}") + self.results.append({ + "test_name": test_name, + "error": str(e), + "status": "failed" + }) + + def run_single_test(self, config): + """运行单个测试""" + # 具体测试逻辑 + pass + + def generate_report(self, format="html"): + """生成报告""" + if format == "html": + return self.generate_html_report() + elif format == "pdf": + return self.generate_pdf_report() + elif format == "markdown": + return self.generate_markdown_report() + + def generate_html_report(self): + """生成HTML报告""" + template = """ + + + 网络测试报告 + + + +

网络测试报告

+

生成时间: {{ timestamp }}

+ +

测试概览

+ + + + + + + + + {% for result in results %} + + + + + + + + {% endfor %} +
测试名称带宽(Mbps)延迟(ms)丢包率(%)状态
{{ result.test_name }}{{ result.bandwidth | default('N/A') }}{{ result.latency | default('N/A') }}{{ result.loss | default('N/A') }}{{ result.status }}
+ +

详细结果

+ {% for result in results %} +

{{ result.test_name }}

+
{{ result.raw_output }}
+ {% endfor %} + + + """ + + # 使用模板引擎渲染 + # ... + + return html_content +``` + +#### 6.3.2 测试场景定义文件 +```yaml +# tests.yaml +tests: + # 基础连通性测试 + basic_connectivity: + description: "基础连通性测试" + server: "192.168.1.1" + port: 5201 + duration: 30 + parallel: 1 + expected: + bandwidth_min: 800 # Mbps + latency_max: 10 # ms + loss_max: 0.1 # % + + # 压力测试 + stress_test: + description: "多流压力测试" + server: "192.168.1.1" + duration: 300 + parallel: 16 + bandwidth: "1G" + expected: + bandwidth_min: 900 + + # 双向测试 + bidirectional_test: + description: "双向带宽测试" + server: "192.168.1.1" + duration: 60 + parallel: 8 + bidirectional: true + + # 不同协议测试 + protocol_tests: + - name: "tcp_test" + protocol: "tcp" + duration: 30 + - name: "udp_test" + protocol: "udp" + duration: 30 + bandwidth: "100M" + +schedule: + daily: "02:00" + weekly: "sunday 03:00" + monthly: "1 04:00" + +reporting: + formats: ["html", "pdf", "email"] + recipients: ["admin@example.com"] + thresholds: + warning: 80% + critical: 90% +``` + +### 6.4 网络质量评分系统 + +#### 6.4.1 评分算法设计 +```python +class NetworkQualityScorer: + def __init__(self, weights=None): + # 默认权重 + self.weights = weights or { + "bandwidth": 0.4, # 带宽权重 40% + "latency": 0.3, # 延迟权重 30% + "loss": 0.2, # 丢包权重 20% + "jitter": 0.1, # 抖动权重 10% + } + + # 基准值(可根据网络类型调整) + self.baselines = { + "lan": { + "bandwidth": 1000, # 1Gbps + "latency": 1, # 1ms + "loss": 0, # 0% + "jitter": 0.1, # 0.1ms + }, + "wan": { + "bandwidth": 100, # 100Mbps + "latency": 50, # 50ms + "loss": 0.1, # 0.1% + "jitter": 5, # 5ms + }, + "internet": { + "bandwidth": 50, # 50Mbps + "latency": 100, # 100ms + "loss": 0.5, # 0.5% + "jitter": 10, # 10ms + } + } + + def calculate_score(self, results, network_type="wan"): + """计算网络质量分数(0-100)""" + baseline = self.baselines[network_type] + + scores = {} + + # 带宽得分(越高越好) + bandwidth_score = min( + 100, + (results.get("bandwidth", 0) / baseline["bandwidth"]) * 100 + ) + + # 延迟得分(越低越好,需要转换) + latency = results.get("latency", float('inf')) + if latency <= baseline["latency"]: + latency_score = 100 + else: + # 延迟加倍,分数减半 + latency_score = max( + 0, + 100 * (baseline["latency"] / latency) + ) + + # 丢包得分(0丢包得100分) + loss = results.get("loss", 100) # 默认100%丢包 + if loss <= baseline["loss"]: + loss_score = 100 + else: + loss_score = max( + 0, + 100 * (1 - loss / 100) # 转换为比例 + ) + + # 抖动得分 + jitter = results.get("jitter", float('inf')) + if jitter <= baseline["jitter"]: + jitter_score = 100 + else: + jitter_score = max( + 0, + 100 * (baseline["jitter"] / jitter) + ) + + # 加权总分 + total_score = ( + bandwidth_score * self.weights["bandwidth"] + + latency_score * self.weights["latency"] + + loss_score * self.weights["loss"] + + jitter_score * self.weights["jitter"] + ) + + return { + "total": round(total_score, 1), + "components": { + "bandwidth": round(bandwidth_score, 1), + "latency": round(latency_score, 1), + "loss": round(loss_score, 1), + "jitter": round(jitter_score, 1), + }, + "details": { + "bandwidth_actual": results.get("bandwidth"), + "latency_actual": results.get("latency"), + "loss_actual": results.get("loss"), + "jitter_actual": results.get("jitter"), + } + } + + def get_quality_level(self, score): + """根据分数获取质量等级""" + if score >= 90: + return {"level": "优秀", "color": "green", "emoji": "✅"} + elif score >= 80: + return {"level": "良好", "color": "blue", "emoji": "👍"} + elif score >= 60: + return {"level": "一般", "color": "yellow", "emoji": "⚠️"} + elif score >= 40: + return {"level": "较差", "color": "orange", "emoji": "🔶"} + else: + return {"level": "差", "color": "red", "emoji": "❌"} + + def generate_quality_report(self, test_results): + """生成质量报告""" + report = { + "timestamp": datetime.now().isoformat(), + "tests": [], + "summary": { + "average_score": 0, + "best_test": None, + "worst_test": None, + "recommendations": [] + } + } + + total_score = 0 + best_score = -1 + worst_score = 101 + + for test in test_results: + score_result = self.calculate_score(test["metrics"]) + quality = self.get_quality_level(score_result["total"]) + + test_report = { + "name": test["name"], + "score": score_result["total"], + "quality": quality, + "details": score_result + } + + report["tests"].append(test_report) + + # 更新统计 + total_score += score_result["total"] + + if score_result["total"] > best_score: + best_score = score_result["total"] + report["summary"]["best_test"] = test["name"] + + if score_result["total"] < worst_score: + worst_score = score_result["total"] + report["summary"]["worst_test"] = test["name"] + + # 计算平均分 + if report["tests"]: + report["summary"]["average_score"] = total_score / len(report["tests"]) + + # 生成建议 + report["summary"]["recommendations"] = self.generate_recommendations(report) + + return report + + def generate_recommendations(self, report): + """根据测试结果生成改进建议""" + recommendations = [] + + for test in report["tests"]: + details = test["details"]["details"] + components = test["details"]["components"] + + # 带宽相关建议 + if components["bandwidth"] < 80: + actual = details.get("bandwidth_actual", 0) + expected = self.baselines["wan"]["bandwidth"] + recommendations.append( + f"测试 '{test['name']}' 带宽较低 ({actual}Mbps vs 预期{expected}Mbps)。" + "建议检查:1.网线质量 2.网络设备规格 3.是否有带宽限制" + ) + + # 延迟相关建议 + if components["latency"] < 80: + actual = details.get("latency_actual", 0) + recommendations.append( + f"测试 '{test['name']}' 延迟较高 ({actual}ms)。" + "建议:1.优化路由 2.减少网络跳数 3.检查网络设备负载" + ) + + # 丢包相关建议 + if components["loss"] < 80: + actual = details.get("loss_actual", 0) + recommendations.append( + f"测试 '{test['name']}' 丢包率较高 ({actual}%)。" + "建议:1.检查网络线路 2.优化MTU设置 3.检查网络设备错误计数" + ) + + # 去重 + return list(set(recommendations)) +``` + +#### 6.4.2 可视化质量报告 +```python +def create_quality_dashboard(report): + """创建质量仪表板""" + import matplotlib.pyplot as plt + import pandas as pd + + # 准备数据 + tests = [t["name"] for t in report["tests"]] + scores = [t["score"] for t in report["tests"]] + colors = [t["quality"]["color"] for t in report["tests"]] + + # 创建图表 + fig, axes = plt.subplots(2, 2, figsize=(15, 10)) + + # 1. 总分柱状图 + axes[0, 0].bar(tests, scores, color=colors) + axes[0, 0].set_title("各测试总分") + axes[0, 0].set_ylabel("分数 (0-100)") + axes[0, 0].set_ylim(0, 100) + axes[0, 0].tick_params(axis='x', rotation=45) + + # 2. 各指标雷达图 + categories = ['带宽', '延迟', '丢包', '抖动'] + N = len(categories) + + for i, test in enumerate(report["tests"]): + values = [ + test["details"]["components"]["bandwidth"], + test["details"]["components"]["latency"], + test["details"]["components"]["loss"], + test["details"]["components"]["jitter"] + ] + values += values[:1] # 闭合雷达图 + + angles = [n / float(N) * 2 * 3.14159 for n in range(N)] + angles += angles[:1] + + ax = axes[0, 1] + ax.plot(angles, values, label=test["name"]) + ax.fill(angles, values, alpha=0.1) + + axes[0, 1].set_title("各测试指标雷达图") + axes[0, 1].legend() + + # 3. 时间趋势图(如果有历史数据) + # ... + + # 4. 质量分布饼图 + quality_counts = {} + for test in report["tests"]: + level = test["quality"]["level"] + quality_counts[level] = quality_counts.get(level, 0) + 1 + + axes[1, 0].pie( + quality_counts.values(), + labels=quality_counts.keys(), + autopct='%1.1f%%', + colors=['green', 'blue', 'yellow', 'orange', 'red'][:len(quality_counts)] + ) + axes[1, 0].set_title("质量等级分布") + + # 5. 详细数据表格 + axes[1, 1].axis('tight') + axes[1, 1].axis('off') + + table_data = [] + for test in report["tests"]: + table_data.append([ + test["name"], + f"{test['score']:.1f}", + test["quality"]["level"], + f"{test['details']['details'].get('bandwidth_actual', 'N/A')}", + f"{test['details']['details'].get('latency_actual', 'N/A')}ms", + f"{test['details']['details'].get('loss_actual', 'N/A')}%" + ]) + + table = axes[1, 1].table( + cellText=table_data, + colLabels=["测试", "分数", "等级", "带宽", "延迟", "丢包"], + loc='center', + cellLoc='center' + ) + table.auto_set_font_size(False) + table.set_fontsize(9) + table.scale(1, 1.5) + + plt.tight_layout() + plt.savefig("network_quality_report.png", dpi=300, bbox_inches='tight') + plt.show() + + return fig +``` + +--- + +## 第七章:安全考虑与最佳实践 + +### 7.1 安全配置建议 + +#### 7.1.1 服务器安全 +**不要将iperf服务器长期暴露在公网**,除非: +1. 有认证机制 +2. 有访问控制 +3. 有日志监控 +4. 有带宽限制 + +**推荐的安全配置**: +```bash +# 使用认证 +iperf3 -s --username admin --rsa-private-key-path /path/to/key + +# 限制带宽 +iperf3 -s --server-bitrate-limit 100M + +# 限制连接时间 +iperf3 -s --idle-timeout 300 --server-max-duration 3600 + +# 使用非标准端口 +iperf3 -s -p 15201 + +# 绑定特定IP +iperf3 -s -B 192.168.1.100 +``` + +#### 7.1.2 防火墙配置 +**必要的最小规则**: +``` +# 只允许特定IP访问 +iptables -A INPUT -p tcp --dport 5201 -s 192.168.1.0/24 -j ACCEPT +iptables -A INPUT -p tcp --dport 5201 -j DROP + +# 限制连接速率 +iptables -A INPUT -p tcp --dport 5201 -m limit --limit 10/min -j ACCEPT +iptables -A INPUT -p tcp --dport 5201 -j DROP +``` + +### 7.2 性能测试最佳实践 + +#### 7.2.1 测试环境准备 +**测试前检查清单**: +``` +□ 1. 确认网络拓扑 +□ 2. 记录设备型号和固件版本 +□ 3. 检查线缆质量(CAT5e以上) +□ 4. 确认端口协商状态(千兆/万兆) +□ 5. 关闭节能模式(EEE) +□ 6. 更新网卡驱动 +□ 7. 调整TCP参数(如果需要) +□ 8. 关闭无关应用程序 +□ 9. 清理ARP缓存 +□ 10. 记录测试前计数器 +``` + +#### 7.2.2 测试方法论 +**科学的测试步骤**: +1. **基线测试**: + - 最低负载测试 + - 单流测试 + - 记录基准值 + +2. **增量测试**: + - 逐步增加负载 + - 观察性能变化 + - 找到拐点 + +3. **压力测试**: + - 长时间满负载 + - 测试稳定性 + - 观察错误率 + +4. **恢复测试**: + - 停止压力后 + - 测试恢复时间 + - 验证弹性 + +#### 7.2.3 结果验证 +**确保结果可信的方法**: +1. **重复测试**:至少3次,取平均值 +2. **交叉验证**:用不同工具验证 +3. **双向验证**:测试两个方向 +4. **分段验证**:分段测试定位问题 +5. **时间验证**:不同时间测试 + +### 7.3 避免常见陷阱 + +#### 7.3.1 技术陷阱 +**避免这些常见错误**: + +1. **忽视CPU性能**: + - iperf3是单线程的 + - 高速测试需要多核CPU + - 使用`-A`参数绑定CPU + +2. **忘记窗口缩放**: + - 高速高延迟需要大窗口 + - 确保窗口缩放启用 + - 调整系统参数 + +3. **MTU不匹配**: + - 检查路径MTU + - 避免分片 + - 适当调整MSS + +4. **缓冲区不足**: + - 增加socket缓冲区 + - 调整系统参数 + - 验证实际使用 + +#### 7.3.2 操作陷阱 +**测试时的注意事项**: + +1. **不要在生产高峰测试**: + - 选择非业务时间 + - 提前通知相关人员 + - 做好回滚准备 + +2. **注意带宽占用**: + - 从低带宽开始 + - 逐步增加 + - 监控影响 + +3. **保存原始数据**: + - 保存iperf原始输出 + - 记录测试环境 + - 保存配置参数 + +4. **考虑测试影响**: + - 对网络设备的影响 + - 对其他应用的影响 + - 对监控系统的影响 + +--- + +## 第八章:故障排除手册 + +### 8.1 常见错误与解决方案 + +#### 8.1.1 连接问题 +**错误:`connect failed: Connection refused`** + +**可能原因**: +1. 服务器未运行 +2. 端口错误 +3. 防火墙阻挡 + +**解决步骤**: +``` +1. 检查服务器是否运行:ps aux | grep iperf3 +2. 检查端口是否正确:netstat -tlnp | grep 5201 +3. 检查防火墙:iptables -L -n +4. 尝试telnet测试:telnet 服务器IP 端口 +``` + +**错误:`connect failed: Connection timed out`** + +**可能原因**: +1. 网络不通 +2. 路由问题 +3. 中间设备丢弃 + +**解决步骤**: +``` +1. ping测试连通性 +2. traceroute查看路径 +3. 检查中间设备ACL +4. 检查MTU问题 +``` + +#### 8.1.2 性能问题 +**问题:速度远低于预期** + +**排查步骤**: +``` +步骤1:测试本地回环 → 验证工具 +步骤2:测试同交换机 → 验证本地网络 +步骤3:逐跳测试 → 定位问题段 +步骤4:检查设备计数器 → 查找错误 +``` + +**常见原因**: +1. **网卡协商问题**: + ```bash + # 检查协商状态 + ethtool eth0 + + # 强制千兆 + ethtool -s eth0 speed 1000 duplex full autoneg off + ``` + +2. **TCP参数问题**: + ```bash + # 检查窗口大小 + sysctl net.ipv4.tcp_window_scaling + + # 检查缓冲区 + sysctl net.core.rmem_max + sysctl net.core.wmem_max + ``` + +3. **系统限制问题**: + ```bash + # 检查文件描述符限制 + ulimit -n + + # 检查CPU频率 + cpupower frequency-info + ``` + +#### 8.1.3 稳定性问题 +**问题:测试结果波动大** + +**可能原因**: +1. 网络拥塞 +2. 无线干扰 +3. 设备负载 +4. 其他应用影响 + +**诊断方法**: +1. **时间分析**: + - 不同时间测试 + - 寻找规律 + +2. **对比分析**: + - 与其他链路对比 + - 与历史数据对比 + +3. **监控分析**: + - 实时监控网络流量 + - 监控设备负载 + +### 8.2 高级诊断技巧 + +#### 8.2.1 使用tcpdump分析 +**捕获iperf流量分析**: +```bash +# 在服务器端捕获 +tcpdump -i eth0 -w iperf.pcap port 5201 + +# 分析TCP序列号 +tcpdump -r iperf.pcap -n 'tcp port 5201' | head -20 + +# 查看重传 +tcpdump -r iperf.pcap -n 'tcp port 5201 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack' +``` + +#### 8.2.2 使用系统工具分析 +**综合性能分析**: +```bash +# 实时监控 +nethogs eth0 # 查看每个连接带宽 +iftop -i eth0 # 查看实时流量 +iotop # 查看磁盘IO +htop # 查看CPU/内存 + +# 网络统计 +sar -n DEV 1 # 网络设备统计 +sar -n TCP 1 # TCP统计 +sar -n EDEV 1 # 错误统计 +``` + +#### 8.2.3 使用专业工具分析 +**深入分析建议**: +1. **Wireshark**:详细协议分析 +2. **perf**:系统性能分析 +3. **systemtap**:内核级分析 +4. **bpftrace**:现代性能分析 + +### 8.3 应急处理方案 + +#### 8.3.1 测试导致网络故障 +**立即停止测试**: +```bash +# 快速停止所有iperf进程 +pkill -9 iperf3 + +# 清理连接 +ss -K dst 服务器IP dport = 5201 +``` + +**恢复网络**: +```bash +# 刷新ARP +ip neigh flush dev eth0 + +# 清理conntrack +conntrack -F + +# 重启网络服务 +systemctl restart network +``` + +#### 8.3.2 数据采集与保存 +**故障时收集信息**: +```bash +# 收集系统信息 +dmesg -T > dmesg.log +journalctl -xe > journal.log + +# 收集网络信息 +ip addr > ip_addr.log +ip route > ip_route.log +ss -tulnp > ss.log +netstat -s > netstat_s.log + +# 收集设备信息 +ethtool -S eth0 > ethtool_S.log +ethtool -k eth0 > ethtool_k.log + +# 打包所有日志 +tar czf debug_$(date +%Y%m%d_%H%M%S).tar.gz *.log +``` + +--- + +## 第九章:扩展与定制开发 + +### 9.1 插件系统设计 + +#### 9.1.1 插件架构 +```python +# plugin_base.py +import abc +from typing import Dict, Any + +class IperfPlugin(abc.ABC): + """插件基类""" + + def __init__(self, name, version): + self.name = name + self.version = version + + @abc.abstractmethod + def before_test(self, config: Dict[str, Any]) -> Dict[str, Any]: + """测试前调用,可以修改配置""" + pass + + @abc.abstractmethod + def during_test(self, output_line: str) -> None: + """测试过程中每行输出调用""" + pass + + @abc.abstractmethod + def after_test(self, results: Dict[str, Any]) -> Dict[str, Any]: + """测试后调用,可以处理结果""" + pass + + @abc.abstractmethod + def get_ui_widget(self): + """返回插件的UI部件""" + pass + +# plugin_manager.py +class PluginManager: + def __init__(self): + self.plugins = {} + self.load_plugins() + + def load_plugins(self): + """动态加载插件""" + import importlib + import pkgutil + + plugin_packages = ['plugins'] + + for package_name in plugin_packages: + try: + package = importlib.import_module(package_name) + for _, module_name, _ in pkgutil.iter_modules(package.__path__): + module = importlib.import_module(f"{package_name}.{module_name}") + + for attr_name in dir(module): + attr = getattr(module, attr_name) + + if (isinstance(attr, type) and + issubclass(attr, IperfPlugin) and + attr != IperfPlugin): + + plugin_instance = attr() + self.plugins[plugin_instance.name] = plugin_instance + + except ImportError: + continue + + def run_before_hooks(self, config): + """运行所有before_test钩子""" + for plugin in self.plugins.values(): + config = plugin.before_test(config) + return config + + def run_during_hooks(self, output_line): + """运行所有during_test钩子""" + for plugin in self.plugins.values(): + plugin.during_test(output_line) + + def run_after_hooks(self, results): + """运行所有after_test钩子""" + for plugin in self.plugins.values(): + results = plugin.after_test(results) + return results +``` + +#### 9.1.2 示例插件 +```python +# plugins/bandwidth_monitor.py +import time +from typing import Dict, Any +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QProgressBar + +class BandwidthMonitorPlugin(IperfPlugin): + """带宽监控插件""" + + def __init__(self): + super().__init__("带宽监控", "1.0") + self.start_time = None + self.total_bytes = 0 + self.max_bandwidth = 0 + self.ui_widget = None + + def before_test(self, config: Dict[str, Any]) -> Dict[str, Any]: + self.start_time = time.time() + self.total_bytes = 0 + self.max_bandwidth = 0 + return config + + def during_test(self, output_line: str) -> None: + # 解析输出行,提取带宽信息 + if "Mbits/sec" in output_line or "Gbits/sec" in output_line: + # 这里添加解析逻辑 + pass + + def after_test(self, results: Dict[str, Any]) -> Dict[str, Any]: + if self.start_time: + duration = time.time() - self.start_time + avg_bandwidth = (self.total_bytes * 8) / duration / 1e6 # Mbps + + results["plugin_stats"] = { + "total_bytes": self.total_bytes, + "average_bandwidth_mbps": avg_bandwidth, + "max_bandwidth_mbps": self.max_bandwidth, + "duration": duration + } + + return results + + def get_ui_widget(self): + if not self.ui_widget: + self.ui_widget = QWidget() + layout = QVBoxLayout() + + self.current_label = QLabel("当前带宽: --") + self.average_label = QLabel("平均带宽: --") + self.max_label = QLabel("最大带宽: --") + self.progress_bar = QProgressBar() + + layout.addWidget(self.current_label) + layout.addWidget(self.average_label) + layout.addWidget(self.max_label) + layout.addWidget(self.progress_bar) + + self.ui_widget.setLayout(layout) + + return self.ui_widget +``` + +### 9.2 API接口设计 + +#### 9.2.1 REST API服务 +```python +# api_server.py +from flask import Flask, request, jsonify +import threading +import time + +app = Flask(__name__) + +class APIServer: + def __init__(self, iperf_gui): + self.gui = iperf_gui + self.test_thread = None + self.current_test = None + + def run(self, host='0.0.0.0', port=5000): + """启动API服务器""" + app.run(host=host, port=port, threaded=True) + + @app.route('/api/test/start', methods=['POST']) + def start_test(): + """启动测试""" + data = request.json + + if self.current_test and self.current_test.is_alive(): + return jsonify({"error": "测试正在进行中"}), 409 + + # 准备测试参数 + params = self.prepare_params(data) + + # 在新线程中运行测试 + self.test_thread = threading.Thread( + target=self.run_test_in_thread, + args=(params,) + ) + self.test_thread.start() + + return jsonify({ + "status": "started", + "test_id": str(int(time.time())) + }) + + @app.route('/api/test/stop', methods=['POST']) + def stop_test(): + """停止测试""" + if self.current_test: + self.current_test.stop() + return jsonify({"status": "stopped"}) + else: + return jsonify({"error": "没有正在运行的测试"}), 404 + + @app.route('/api/test/status', methods=['GET']) + def get_status(): + """获取测试状态""" + if self.current_test and self.current_test.is_alive(): + return jsonify({ + "status": "running", + "progress": self.current_test.get_progress(), + "results": self.current_test.get_partial_results() + }) + else: + return jsonify({"status": "stopped"}) + + @app.route('/api/config', methods=['GET', 'POST']) + def config(): + """配置管理""" + if request.method == 'GET': + return jsonify(self.gui.get_current_config()) + else: + config = request.json + self.gui.apply_config(config) + return jsonify({"status": "applied"}) + + def run_test_in_thread(self, params): + """在线程中运行测试""" + self.current_test = self.gui.start_test_with_params(params) + + while self.current_test.is_alive(): + time.sleep(0.1) + + self.current_test = None +``` + +#### 9.2.2 WebSocket实时数据 +```python +# websocket_server.py +from flask_socketio import SocketIO, emit +import json + +socketio = SocketIO(app, cors_allowed_origins="*") + +@socketio.on('connect') +def handle_connect(): + print('客户端连接') + emit('connected', {'data': '连接成功'}) + +@socketio.on('start_test') +def handle_start_test(data): + """通过WebSocket启动测试""" + test_id = start_test_async(data) + emit('test_started', {'test_id': test_id}) + + # 实时推送结果 + def send_updates(): + while test_is_running(test_id): + results = get_latest_results(test_id) + emit('test_update', results) + socketio.sleep(0.5) + + socketio.start_background_task(send_updates) + +@socketio.on('stop_test') +def handle_stop_test(data): + test_id = data.get('test_id') + stop_test(test_id) + emit('test_stopped', {'test_id': test_id}) +``` + +### 9.3 自定义报告生成 + +#### 9.3.1 报告模板系统 +```python +# report_generator.py +from jinja2 import Environment, FileSystemLoader +import pdfkit +import pandas as pd + +class ReportGenerator: + def __init__(self, template_dir='templates'): + self.env = Environment( + loader=FileSystemLoader(template_dir), + extensions=['jinja2.ext.do'] + ) + + # 注册自定义过滤器 + self.env.filters['format_bandwidth'] = self.format_bandwidth + self.env.filters['format_time'] = self.format_time + self.env.filters['quality_color'] = self.quality_color + + def generate_report(self, data, template_name, output_format='html'): + """生成报告""" + template = self.env.get_template(template_name) + + # 渲染模板 + html_content = template.render(**data) + + if output_format == 'html': + return html_content + elif output_format == 'pdf': + return self.html_to_pdf(html_content) + elif output_format == 'docx': + return self.html_to_docx(html_content) + else: + raise ValueError(f"不支持的格式: {output_format}") + + def format_bandwidth(self, value, unit='auto'): + """格式化带宽显示""" + if unit == 'auto': + if value >= 1000: + return f"{value/1000:.2f} Gbps" + elif value >= 1: + return f"{value:.2f} Mbps" + else: + return f"{value*1000:.2f} Kbps" + elif unit == 'G': + return f"{value/1000:.2f} Gbps" + elif unit == 'M': + return f"{value:.2f} Mbps" + elif unit == 'K': + return f"{value*1000:.2f} Kbps" + + def format_time(self, seconds): + """格式化时间显示""" + if seconds < 60: + return f"{seconds:.1f} 秒" + elif seconds < 3600: + minutes = int(seconds // 60) + secs = seconds % 60 + return f"{minutes} 分 {secs:.0f} 秒" + else: + hours = int(seconds // 3600) + minutes = int((seconds % 3600) // 60) + return f"{hours} 小时 {minutes} 分" + + def quality_color(self, score): + """根据分数返回颜色""" + if score >= 90: + return "#28a745" # 绿色 + elif score >= 80: + return "#17a2b8" # 蓝色 + elif score >= 60: + return "#ffc107" # 黄色 + elif score >= 40: + return "#fd7e14" # 橙色 + else: + return "#dc3545" # 红色 + + def html_to_pdf(self, html_content): + """HTML转PDF""" + options = { + 'page-size': 'A4', + 'margin-top': '0.75in', + 'margin-right': '0.75in', + 'margin-bottom': '0.75in', + 'margin-left': '0.75in', + 'encoding': "UTF-8", + 'no-outline': None, + 'enable-local-file-access': None + } + + pdf = pdfkit.from_string(html_content, False, options=options) + return pdf + + def generate_comparison_report(self, results_list, baseline=None): + """生成对比报告""" + # 创建DataFrame + df = pd.DataFrame(results_list) + + # 计算统计 + stats = { + '测试次数': len(df), + '平均带宽': df['bandwidth'].mean(), + '最大带宽': df['bandwidth'].max(), + '最小带宽': df['bandwidth'].min(), + '带宽标准差': df['bandwidth'].std(), + '平均延迟': df['latency'].mean(), + '平均丢包': df['loss'].mean(), + } + + if baseline: + stats['与基线差异'] = { + '带宽': ((df['bandwidth'].mean() - baseline['bandwidth']) / baseline['bandwidth']) * 100, + '延迟': ((df['latency'].mean() - baseline['latency']) / baseline['latency']) * 100, + } + + # 生成报告数据 + report_data = { + 'statistics': stats, + 'results': df.to_dict('records'), + 'charts': { + 'bandwidth_trend': self.create_bandwidth_chart(df), + 'quality_distribution': self.create_quality_distribution(df), + 'comparison_chart': self.create_comparison_chart(df, baseline) if baseline else None + } + } + + return self.generate_report(report_data, 'comparison_report.html') + + def create_bandwidth_chart(self, df): + """创建带宽趋势图数据""" + # 这里生成图表数据,可以是Plotly、Chart.js等格式 + chart_data = { + 'labels': df['timestamp'].tolist(), + 'datasets': [{ + 'label': '带宽 (Mbps)', + 'data': df['bandwidth'].tolist(), + 'borderColor': 'rgb(75, 192, 192)', + 'backgroundColor': 'rgba(75, 192, 192, 0.2)', + }] + } + return chart_data +``` + +#### 9.3.2 报告模板示例 +```html + + + + + + + 网络测试对比报告 + + + + +
+

网络性能测试对比报告

+

生成时间: {{ timestamp }}

+

测试次数: {{ statistics.测试次数 }} 次

+
+ +
+
+

带宽性能

+
{{ statistics.平均带宽|format_bandwidth }}
+
平均带宽
+

范围: {{ statistics.最小带宽|format_bandwidth }} - {{ statistics.最大带宽|format_bandwidth }}

+
+ +
+

网络质量

+
{{ statistics.平均延迟|round(2) }} ms
+
平均延迟
+

丢包率: {{ statistics.平均丢包|round(3) }}%

+
+ + {% if statistics.与基线差异 %} +
+

与基线对比

+
+ {{ statistics.与基线差异.带宽|round(2) }}% +
+
带宽变化
+

延迟变化: {{ statistics.与基线差异.延迟|round(2) }}%

+
+ {% endif %} +
+ +
+ +
+ +

详细测试结果

+ + + + + + + + + + + + + {% for result in results %} + + + + + + + + + {% endfor %} + +
时间带宽延迟丢包质量评分备注
{{ result.timestamp }}{{ result.bandwidth|format_bandwidth }}{{ result.latency|round(2) }} ms{{ result.loss|round(3) }}% + + {{ result.quality_score|round(1) }} + {{ result.notes or '' }}
+ + {% if recommendations %} +
+

改进建议

+ +
+ {% endif %} + + + + + + +``` + +### 9.4 测试场景库 + +#### 9.4.1 预定义测试场景 +```python +# test_scenarios.py +class TestScenarioLibrary: + """测试场景库""" + + SCENARIOS = { + # 家庭网络场景 + "home_network_basic": { + "name": "家庭网络基础测试", + "description": "测试家庭网络基本性能", + "tests": [ + { + "name": "局域网有线测试", + "server": "192.168.1.1", + "duration": 30, + "parallel": 1, + "expected_bandwidth": 900 # Mbps + }, + { + "name": "Wi-Fi近距离测试", + "server": "192.168.1.1", + "duration": 30, + "parallel": 4, + "wireless": True, + "expected_bandwidth": 300 # Mbps,根据Wi-Fi规格调整 + }, + { + "name": "互联网下载测试", + "server": "ping.online.net", + "duration": 60, + "parallel": 8, + "expected_bandwidth": "80% of ISP speed" + } + ] + }, + + # 企业网络场景 + "enterprise_network_validation": { + "name": "企业网络验收测试", + "description": "企业网络部署后的全面验证", + "tests": [ + { + "name": "核心交换机性能测试", + "duration": 300, + "parallel": 32, + "bidirectional": True, + "expected_bandwidth": "line rate" + }, + { + "name": "跨部门通信测试", + "duration": 180, + "parallel": 16, + "multiple_servers": True, + "expected_loss": 0 + }, + { + "name": "互联网出口测试", + "duration": 600, + "parallel": 8, + "long_running": True, + "monitor_stability": True + } + ] + }, + + # 云服务场景 + "cloud_migration_validation": { + "name": "云迁移网络验证", + "description": "验证本地到云的网络性能", + "tests": [ + { + "name": "本地到云单向带宽", + "direction": "upload", + "duration": 300, + "parallel": 16, + "monitor": ["bandwidth", "loss", "latency"] + }, + { + "name": "云到本地单向带宽", + "direction": "download", + "duration": 300, + "parallel": 16 + }, + { + "name": "双向并发测试", + "duration": 600, + "parallel": 8, + "bidirectional": True, + "stress_test": True + }, + { + "name": "不同时段稳定性", + "schedule": ["00:00", "06:00", "12:00", "18:00"], + "duration": 1800, + "monitor_variation": True + } + ] + }, + + # 实时应用场景 + "realtime_application_simulation": { + "name": "实时应用模拟测试", + "description": "模拟VoIP、视频会议等实时应用", + "tests": [ + { + "name": "VoIP质量测试", + "protocol": "udp", + "bandwidth": "0.1M", # 100Kbps,典型VoIP + "duration": 300, + "monitor": ["jitter", "loss", "latency"], + "expected_jitter": 20, # ms + "expected_loss": 1, # % + "expected_latency": 150 # ms + }, + { + "name": "视频会议测试", + "protocol": "udp", + "bandwidth": "4M", # 720p视频 + "duration": 600, + "parallel": 4, # 模拟多参会者 + "expected_loss": 0.5 + }, + { + "name": "在线游戏测试", + "protocol": "udp", + "bandwidth": "0.5M", + "duration": 1800, + "packet_size": 512, # 典型游戏包大小 + "expected_latency": 50 + } + ] + }, + + # 存储网络场景 + "storage_network_performance": { + "name": "存储网络性能测试", + "description": "测试NAS、SAN等存储网络性能", + "tests": [ + { + "name": "顺序读写测试", + "protocol": "tcp", + "duration": 300, + "window_size": "1M", + "parallel": 1, + "test_pattern": "sequential" + }, + { + "name": "随机读写测试", + "protocol": "tcp", + "duration": 300, + "parallel": 32, + "test_pattern": "random", + "io_size": "4K" # 模拟数据库IO + }, + { + "name": "混合读写测试", + "protocol": "tcp", + "duration": 600, + "parallel": 16, + "bidirectional": True, + "test_pattern": "mixed" + } + ] + }, + + # 网络安全场景 + "network_security_validation": { + "name": "网络安全策略验证", + "description": "验证防火墙、IPS等安全设备的影响", + "tests": [ + { + "name": "基础策略测试", + "protocol": "tcp", + "port": 80, + "duration": 60, + "baseline": True + }, + { + "name": "IPS深度检测影响", + "protocol": "tcp", + "port": 80, + "duration": 60, + "ips_enabled": True, + "compare_with": "基础策略测试" + }, + { + "name": "不同包大小测试", + "protocol": "tcp", + "duration": 60, + "packet_sizes": [64, 512, 1500, 9000], + "compare_performance": True + }, + { + "name": "并发连接数测试", + "protocol": "tcp", + "duration": 300, + "parallel": [1, 10, 100, 1000], + "test_connection_limit": True + } + ] + } + } + + @classmethod + def get_scenario(cls, scenario_id): + """获取测试场景""" + return cls.SCENARIOS.get(scenario_id) + + @classmethod + def list_scenarios(cls): + """列出所有测试场景""" + return [ + { + "id": scenario_id, + "name": config["name"], + "description": config["description"], + "test_count": len(config.get("tests", [])) + } + for scenario_id, config in cls.SCENARIOS.items() + ] + + @classmethod + def execute_scenario(cls, scenario_id, custom_params=None): + """执行测试场景""" + scenario = cls.get_scenario(scenario_id) + if not scenario: + raise ValueError(f"场景不存在: {scenario_id}") + + results = [] + all_passed = True + + for test_config in scenario["tests"]: + # 合并自定义参数 + if custom_params: + test_config.update(custom_params) + + print(f"执行测试: {test_config['name']}") + + try: + # 执行单个测试 + result = cls.execute_single_test(test_config) + + # 验证期望值 + if "expected_bandwidth" in test_config: + expected = test_config["expected_bandwidth"] + actual = result.get("bandwidth", 0) + + if isinstance(expected, str) and "%" in expected: + # 百分比期望,如"80% of ISP speed" + pass # 需要额外逻辑 + elif actual < expected * 0.9: # 允许10%误差 + result["status"] = "failed" + result["message"] = f"带宽未达预期: {actual} < {expected}" + all_passed = False + else: + result["status"] = "passed" + + results.append(result) + + except Exception as e: + results.append({ + "name": test_config.get("name", "未知测试"), + "status": "error", + "error": str(e) + }) + all_passed = False + + return { + "scenario_id": scenario_id, + "scenario_name": scenario["name"], + "all_passed": all_passed, + "results": results, + "summary": cls.generate_scenario_summary(results) + } + + @classmethod + def execute_single_test(cls, test_config): + """执行单个测试""" + # 这里调用iperf3执行测试 + # 简化示例,实际需要调用iperf3 + return { + "name": test_config["name"], + "bandwidth": 950, # 模拟结果 + "latency": 12, + "loss": 0, + "duration": test_config.get("duration", 30) + } + + @classmethod + def generate_scenario_summary(cls, results): + """生成场景测试摘要""" + if not results: + return {} + + total = len(results) + passed = sum(1 for r in results if r.get("status") == "passed") + failed = sum(1 for r in results if r.get("status") == "failed") + errors = sum(1 for r in results if r.get("status") == "error") + + bandwidths = [r.get("bandwidth", 0) for r in results if r.get("bandwidth")] + latencies = [r.get("latency", 0) for r in results if r.get("latency")] + + return { + "total_tests": total, + "passed": passed, + "failed": failed, + "errors": errors, + "pass_rate": (passed / total * 100) if total > 0 else 0, + "avg_bandwidth": sum(bandwidths) / len(bandwidths) if bandwidths else 0, + "avg_latency": sum(latencies) / len(latencies) if latencies else 0, + "min_bandwidth": min(bandwidths) if bandwidths else 0, + "max_bandwidth": max(bandwidths) if bandwidths else 0 + } +``` + +#### 9.4.2 场景执行器 +```python +# scenario_executor.py +import time +from datetime import datetime +from concurrent.futures import ThreadPoolExecutor, as_completed + +class ScenarioExecutor: + """场景执行器""" + + def __init__(self, max_workers=3): + self.max_workers = max_workers + self.executor = ThreadPoolExecutor(max_workers=max_workers) + self.running_tests = {} + self.results = {} + + def execute_scenario_async(self, scenario_id, params=None, callback=None): + """异步执行测试场景""" + future = self.executor.submit( + self._execute_scenario_sync, + scenario_id, params + ) + + test_id = f"test_{int(time.time())}_{scenario_id}" + self.running_tests[test_id] = { + "future": future, + "scenario_id": scenario_id, + "start_time": datetime.now(), + "callback": callback + } + + # 添加完成回调 + future.add_done_callback( + lambda f: self._on_scenario_complete(test_id, f) + ) + + return test_id + + def _execute_scenario_sync(self, scenario_id, params): + """同步执行测试场景""" + from test_scenarios import TestScenarioLibrary + + return TestScenarioLibrary.execute_scenario(scenario_id, params) + + def _on_scenario_complete(self, test_id, future): + """场景完成回调""" + if test_id in self.running_tests: + test_info = self.running_tests.pop(test_id) + + try: + result = future.result() + result["test_id"] = test_id + result["end_time"] = datetime.now() + + self.results[test_id] = result + + # 调用用户回调 + if test_info["callback"]: + test_info["callback"](result) + + # 触发事件 + self._emit_event("scenario_completed", result) + + except Exception as e: + error_result = { + "test_id": test_id, + "status": "error", + "error": str(e), + "end_time": datetime.now() + } + + self.results[test_id] = error_result + self._emit_event("scenario_failed", error_result) + + def execute_scenario_sequence(self, scenario_ids, params_list=None, + interval=30, stop_on_error=False): + """按顺序执行多个场景""" + if params_list is None: + params_list = [{}] * len(scenario_ids) + + sequence_id = f"seq_{int(time.time())}" + sequence_results = { + "sequence_id": sequence_id, + "start_time": datetime.now(), + "scenarios": [], + "status": "running" + } + + all_passed = True + + for i, (scenario_id, params) in enumerate(zip(scenario_ids, params_list)): + print(f"执行场景 {i+1}/{len(scenario_ids)}: {scenario_id}") + + try: + result = self._execute_scenario_sync(scenario_id, params) + result["order"] = i + 1 + + sequence_results["scenarios"].append(result) + + if not result.get("all_passed", True): + all_passed = False + + if stop_on_error: + print(f"场景 {scenario_id} 失败,停止序列执行") + break + + # 场景间间隔 + if i < len(scenario_ids) - 1: + print(f"等待 {interval} 秒后执行下一个场景...") + time.sleep(interval) + + except Exception as e: + error_result = { + "scenario_id": scenario_id, + "order": i + 1, + "status": "error", + "error": str(e) + } + + sequence_results["scenarios"].append(error_result) + all_passed = False + + if stop_on_error: + break + + sequence_results["end_time"] = datetime.now() + sequence_results["status"] = "completed" if all_passed else "failed" + sequence_results["all_passed"] = all_passed + + # 保存序列结果 + self.results[sequence_id] = sequence_results + self._emit_event("sequence_completed", sequence_results) + + return sequence_results + + def get_test_status(self, test_id): + """获取测试状态""" + if test_id in self.running_tests: + future = self.running_tests[test_id]["future"] + + if future.running(): + return {"status": "running"} + elif future.done(): + return {"status": "done"} + else: + return {"status": "pending"} + + elif test_id in self.results: + result = self.results[test_id] + return { + "status": "completed", + "result": result + } + + else: + return {"status": "not_found"} + + def get_all_results(self): + """获取所有结果""" + return self.results + + def clear_results(self, older_than_days=7): + """清理旧结果""" + cutoff_time = datetime.now().timestamp() - (older_than_days * 24 * 3600) + + to_delete = [] + for test_id, result in self.results.items(): + end_time = result.get("end_time") + if end_time and end_time.timestamp() < cutoff_time: + to_delete.append(test_id) + + for test_id in to_delete: + del self.results[test_id] + + return len(to_delete) + + def _emit_event(self, event_type, data): + """触发事件(可扩展为事件总线)""" + # 这里可以实现事件监听器模式 + # 例如:self.event_listeners[event_type].append(callback) + pass + + def stop_all(self): + """停止所有测试""" + self.executor.shutdown(wait=False) + self.running_tests.clear() +``` + +#### 9.4.3 场景UI界面 +```python +# scenario_ui.py +from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QListWidget, + QListWidgetItem, QPushButton, QLabel, QGroupBox, + QTextEdit, QProgressBar, QTreeWidget, QTreeWidgetItem, + QSplitter, QTabWidget) +from PyQt5.QtCore import Qt, QTimer + +class ScenarioUI(QWidget): + """场景管理界面""" + + def __init__(self, executor): + super().__init__() + self.executor = executor + self.current_scenario = None + self.init_ui() + self.load_scenarios() + self.setup_timer() + + def init_ui(self): + """初始化界面""" + layout = QHBoxLayout(self) + + # 左侧:场景列表 + left_panel = QWidget() + left_layout = QVBoxLayout(left_panel) + + # 场景列表 + self.scenario_list = QListWidget() + self.scenario_list.itemClicked.connect(self.on_scenario_selected) + left_layout.addWidget(QLabel("测试场景库")) + left_layout.addWidget(self.scenario_list) + + # 场景描述 + self.scenario_desc = QTextEdit() + self.scenario_desc.setReadOnly(True) + self.scenario_desc.setMaximumHeight(150) + left_layout.addWidget(QLabel("场景描述")) + left_layout.addWidget(self.scenario_desc) + + # 执行按钮 + self.execute_btn = QPushButton("执行选中场景") + self.execute_btn.clicked.connect(self.execute_selected_scenario) + self.execute_btn.setEnabled(False) + left_layout.addWidget(self.execute_btn) + + # 右侧:执行控制面板 + right_panel = QWidget() + right_layout = QVBoxLayout(right_panel) + + # 当前执行状态 + status_group = QGroupBox("执行状态") + status_layout = QVBoxLayout() + + self.current_scenario_label = QLabel("无执行中的场景") + status_layout.addWidget(self.current_scenario_label) + + self.progress_bar = QProgressBar() + status_layout.addWidget(self.progress_bar) + + self.status_text = QTextEdit() + self.status_text.setReadOnly(True) + self.status_text.setMaximumHeight(100) + status_layout.addWidget(self.status_text) + + self.stop_btn = QPushButton("停止当前测试") + self.stop_btn.clicked.connect(self.stop_current_test) + self.stop_btn.setEnabled(False) + status_layout.addWidget(self.stop_btn) + + status_group.setLayout(status_layout) + right_layout.addWidget(status_group) + + # 结果查看 + results_group = QGroupBox("测试结果") + results_layout = QVBoxLayout() + + self.results_tree = QTreeWidget() + self.results_tree.setHeaderLabels(["测试", "状态", "带宽", "延迟", "丢包"]) + results_layout.addWidget(self.results_tree) + + results_group.setLayout(results_layout) + right_layout.addWidget(results_group) + + # 添加到主布局 + splitter = QSplitter(Qt.Horizontal) + splitter.addWidget(left_panel) + splitter.addWidget(right_panel) + splitter.setSizes([300, 500]) + + layout.addWidget(splitter) + + def load_scenarios(self): + """加载场景列表""" + from test_scenarios import TestScenarioLibrary + + scenarios = TestScenarioLibrary.list_scenarios() + + for scenario in scenarios: + item = QListWidgetItem(scenario["name"]) + item.setData(Qt.UserRole, scenario["id"]) + self.scenario_list.addItem(item) + + def on_scenario_selected(self, item): + """场景被选中""" + scenario_id = item.data(Qt.UserRole) + from test_scenarios import TestScenarioLibrary + + scenario = TestScenarioLibrary.get_scenario(scenario_id) + if scenario: + self.current_scenario = scenario_id + + desc = f"名称: {scenario['name']}\n\n" + desc += f"描述: {scenario['description']}\n\n" + desc += f"包含测试: {len(scenario.get('tests', []))} 个\n\n" + desc += "测试项目:\n" + + for test in scenario.get("tests", []): + desc += f" • {test.get('name', '未命名')}\n" + + self.scenario_desc.setText(desc) + self.execute_btn.setEnabled(True) + + def execute_selected_scenario(self): + """执行选中的场景""" + if not self.current_scenario: + return + + # 禁用按钮 + self.execute_btn.setEnabled(False) + self.stop_btn.setEnabled(True) + + # 更新状态 + from test_scenarios import TestScenarioLibrary + scenario = TestScenarioLibrary.get_scenario(self.current_scenario) + self.current_scenario_label.setText(f"执行中: {scenario['name']}") + self.progress_bar.setRange(0, len(scenario.get("tests", []))) + self.progress_bar.setValue(0) + + # 清空结果树 + self.results_tree.clear() + + # 异步执行 + test_id = self.executor.execute_scenario_async( + self.current_scenario, + callback=self.on_scenario_completed + ) + + self.current_test_id = test_id + + def on_scenario_completed(self, result): + """场景完成回调""" + # 在主线程中更新UI + QTimer.singleShot(0, lambda: self.update_scenario_results(result)) + + def update_scenario_results(self, result): + """更新场景结果""" + self.execute_btn.setEnabled(True) + self.stop_btn.setEnabled(False) + + if result.get("all_passed"): + self.current_scenario_label.setText( + f"完成: {result['scenario_name']} (全部通过)" + ) + else: + self.current_scenario_label.setText( + f"完成: {result['scenario_name']} (有失败)" + ) + + # 更新进度条 + self.progress_bar.setValue(self.progress_bar.maximum()) + + # 更新结果树 + for test_result in result.get("results", []): + item = QTreeWidgetItem(self.results_tree) + + item.setText(0, test_result.get("name", "未知")) + + status = test_result.get("status", "unknown") + item.setText(1, status) + + if status == "passed": + item.setForeground(1, Qt.darkGreen) + elif status == "failed": + item.setForeground(1, Qt.darkRed) + elif status == "error": + item.setForeground(1, Qt.darkYellow) + + bandwidth = test_result.get("bandwidth", 0) + item.setText(2, f"{bandwidth:.1f} Mbps" if bandwidth else "N/A") + + latency = test_result.get("latency", 0) + item.setText(3, f"{latency:.1f} ms" if latency else "N/A") + + loss = test_result.get("loss", 0) + item.setText(4, f"{loss:.2f}%" if loss is not None else "N/A") + + # 显示摘要 + summary = result.get("summary", {}) + status_text = f"测试完成于: {result.get('end_time')}\n" + status_text += f"总测试数: {summary.get('total_tests', 0)}\n" + status_text += f"通过率: {summary.get('pass_rate', 0):.1f}%\n" + status_text += f"平均带宽: {summary.get('avg_bandwidth', 0):.1f} Mbps\n" + status_text += f"平均延迟: {summary.get('avg_latency', 0):.1f} ms\n" + + self.status_text.setText(status_text) + + def stop_current_test(self): + """停止当前测试""" + # 这里需要实现停止逻辑 + # 由于测试是在线程中运行的,需要优雅停止 + self.stop_btn.setEnabled(False) + self.current_scenario_label.setText("正在停止...") + + def setup_timer(self): + """设置定时器更新状态""" + self.update_timer = QTimer() + self.update_timer.timeout.connect(self.update_status) + self.update_timer.start(1000) # 每秒更新 + + def update_status(self): + """更新状态""" + if hasattr(self, 'current_test_id'): + status = self.executor.get_test_status(self.current_test_id) + + if status["status"] == "running": + # 更新进度等 + pass +``` + +--- + +## 第十章:版本更新记录 + +### 10.1 版本更新简介 + +#### v1.0.0 (2024-01-01) - 初始版本 +**主要特性**: +1. **完整参数支持**:支持所有 iperf3 命令行参数 +2. **图形化界面**:直观的PyQt5界面 +3. **多标签页设计**:基础配置、高级选项、服务器选项、测试结果、历史记录 +4. **实时结果显示**:测试过程中实时显示结果 +5. **配置管理**:保存和加载测试配置 +6. **历史记录**:记录历次测试结果 +7. **结果导出**:支持导出为文本和CSV格式 + +**技术特点**: +- 使用 QThread 实现异步测试,避免界面卡顿 +- JSON配置文件管理 +- 支持TCP和UDP协议 +- 完整的错误处理和用户反馈 + +#### v1.1.0 (2024-02-01) - 增强版 +**新增功能**: +1. **批量测试支持**:支持定义和执行测试序列 +2. **插件系统**:可扩展的插件架构 +3. **自动化脚本**:Python API接口 +4. **网络质量评分**:自动评估网络质量 +5. **详细报告生成**:HTML/PDF格式报告 + +**优化改进**: +- 性能优化:减少内存使用,提高界面响应 +- 稳定性增强:改进错误处理和恢复机制 +- 用户体验:更直观的界面布局和操作流程 + +#### v1.2.0 (2024-03-01) - 专业版 +**专业功能**: +1. **场景测试库**:预定义各种测试场景 +2. **API服务器**:RESTful API接口 +3. **WebSocket支持**:实时数据传输 +4. **监控集成**:Prometheus和Grafana集成 +5. **企业级报告**:定制化报告模板 + +**高级特性**: +- 分布式测试支持 +- 网络拓扑发现 +- 性能基准对比 +- SLA合规检查 + +#### v1.3.0 (2024-04-01) - 云原生版 +**云环境优化**: +1. **云服务集成**:AWS、Azure、GCP等云平台集成 +2. **容器化支持**:Docker镜像和Kubernetes部署 +3. **微服务架构**:模块化设计,易于扩展 +4. **多云测试**:跨云平台性能对比 + +**现代化特性**: +- 响应式Web界面 +- 移动端适配 +- 实时协作功能 +- 人工智能分析 + +### 10.2 向后兼容性说明 + +#### 10.2.1 配置兼容性 +所有版本的配置文件都保持向后兼容: +- v1.0.0 配置文件可以在所有后续版本中使用 +- 新版本增加的配置项会有默认值 +- 旧版本无法识别的配置项会被忽略 + +#### 10.2.2 API兼容性 +REST API保持版本兼容: +- `/api/v1/` 路径下的API保持稳定 +- 新增功能使用新版本路径 `/api/v2/` +- 废弃的API会有足够长的弃用期 + +#### 10.2.3 数据兼容性 +历史记录和数据格式: +- 所有版本都可以读取旧版本的历史数据 +- 数据迁移工具自动处理格式变化 +- 导出格式保持稳定 + +### 10.3 升级指南 + +#### 10.3.1 从旧版本升级 +**步骤**: +1. **备份现有数据**: + ```bash + cp iperf3_gui_config.json iperf3_gui_config.json.backup + cp history_data.csv history_data.csv.backup + ``` + +2. **安装新版本**: + ```bash + pip install --upgrade iperf3-gui + # 或直接替换文件 + ``` + +3. **运行迁移脚本**(如果需要): + ```bash + python migrate_v1_to_v2.py + ``` + +4. **验证升级**: + - 检查配置是否正确加载 + - 测试基本功能 + - 验证历史数据 + +#### 10.3.2 全新安装 +**推荐步骤**: +1. **环境准备**: + ```bash + # Python环境 + python -m venv venv + source venv/bin/activate # Linux/macOS + # 或 venv\Scripts\activate # Windows + + # 安装依赖 + pip install -r requirements.txt + + # 安装iperf3 + # Windows: 下载并添加到PATH + # Linux: sudo apt-get install iperf3 + # macOS: brew install iperf3 + ``` + +2. **首次运行**: + ```bash + python iperf_gui.py + ``` + +3. **基本配置**: + - 设置常用服务器地址 + - 配置默认测试参数 + - 设置结果保存路径 + +#### 10.3.3 故障排除 +**常见升级问题**: + +1. **配置文件不兼容**: + ``` + 错误:JSON解析错误 + 解决:删除配置文件,程序会创建新的默认配置 + ``` + +2. **依赖包冲突**: + ``` + 错误:ImportError 或版本冲突 + 解决:创建新的虚拟环境,重新安装 + ``` + +3. **历史数据丢失**: + ``` + 现象:历史记录为空 + 解决:检查备份文件,手动导入 + ``` + +4. **性能下降**: + ``` + 现象:新版本运行变慢 + 解决:检查系统资源,调整配置参数 + ``` + +**获取帮助**: +- 查看本文档的故障排除章节 +- 访问GitHub Issues页面 +- 查阅在线文档 + +--- + +## 附录 + +### A. iperf3 命令参数对照表 + +| 图形界面选项 | iperf3 参数 | 说明 | +|------------|------------|------| +| 测试模式 | `-c` / `-s` | 客户端/服务器模式 | +| 服务器地址 | `-c ` | 客户端模式必须 | +| 端口 | `-p ` | 默认5201 | +| 协议 | `-u` | UDP协议 | +| 测试时间 | `-t ` | 测试持续时间 | +| 并行流 | `-P ` | 并行连接数 | +| 带宽限制 | `-b ` | 带宽限制 | +| 窗口大小 | `-w ` | TCP窗口大小 | +| MSS大小 | `-M ` | TCP最大段大小 | +| 缓冲区长度 | `-l ` | 读写缓冲区长度 | +| 传输数据量 | `-n ` | 传输指定数据量 | +| 块数量 | `-k ` | 块数量 | +| 报告间隔 | `-i ` | 报告间隔 | +| 格式 | `--format ` | 输出单位格式 | +| 反向测试 | `-R` | 反向传输 | +| 双向测试 | `--bidir` | 双向同时传输 | +| 连接超时 | `--connect-timeout ` | 连接超时 | +| 绑定设备 | `--bind-dev ` | 绑定网络设备 | +| 绑定主机 | `-B ` | 绑定源地址 | +| 客户端端口 | `--cport ` | 客户端端口 | +| 省略时间 | `-O ` | 跳过开始时间 | +| 标题 | `-T ` | 输出标题 | +| 额外数据 | `--extra-data <str>` | JSON额外数据 | +| 获取服务器输出 | `--get-server-output` | 获取服务器输出 | +| UDP 64位计数器 | `--udp-counters-64bit` | UDP使用64位计数器 | +| 重复负载 | `--repeating-payload` | UDP重复负载 | +| 不分片 | `--dont-fragment` | 设置DF标志 | +| IPv4 only | `-4` | 仅使用IPv4 | +| IPv6 only | `-6` | 仅使用IPv6 | +| TOS | `-S <tos>` | IP服务类型 | +| DSCP | `--dscp <dscp>` | 差分服务代码点 | +| 禁用Nagle | `-N` | 禁用Nagle算法 | +| 零拷贝 | `-Z` | 使用零拷贝 | +| 跳过接收拷贝 | `--skip-rx-copy` | 接收端零拷贝 | +| 接收超时 | `--rcv-timeout <ms>` | 接收超时 | +| 用户名 | `--username <name>` | 认证用户名 | +| RSA公钥路径 | `--rsa-public-key-path <path>` | RSA公钥文件 | +| 文件传输 | `-F <filename>` | 发送文件内容 | +| 单次连接 | `-1` | 服务器单次连接 | +| 守护进程 | `-D` | 守护进程模式 | +| 服务器带宽限制 | `--server-bitrate-limit <rate>` | 服务器带宽限制 | +| 空闲超时 | `--idle-timeout <seconds>` | 空闲超时 | +| 服务器最大持续时间 | `--server-max-duration <seconds>` | 服务器运行时间限制 | +| RSA私钥路径 | `--rsa-private-key-path <path>` | RSA私钥文件 | +| 授权用户路径 | `--authorized-users-path <path>` | 用户配置文件 | +| 时间偏差阈值 | `--time-skew-threshold <seconds>` | 时间偏差阈值 | +| 使用PKCS1填充 | `--use-pkcs1-padding` | RSA使用PKCS1填充 | +| PID文件 | `-I <pidfile>` | 写入PID文件 | +| 日志文件 | `--logfile <filename>` | 日志文件 | +| JSON输出 | `-J` | JSON格式输出 | +| JSON流输出 | `--json-stream` | JSON流输出 | +| 完整JSON流输出 | `--json-stream-full-output` | 完整JSON流 | +| 详细输出 | `-V` | 详细输出 | +| 调试模式 | `-d` 或 `--debug=<level>` | 调试模式 | +| 显示版本 | `-v` | 显示版本 | +| 强制刷新 | `--forceflush` | 强制刷新输出 | +| 时间戳 | `--timestamps[=format]` | 时间戳 | +| CPU亲和性 | `-A <cpuid>` | CPU亲和性 | + +### B. 常见网络速度参考值 + +#### 有线网络: +- **10M以太网**:理论 10 Mbps,实际 9-9.5 Mbps +- **100M以太网**:理论 100 Mbps,实际 94-98 Mbps +- **千兆以太网**:理论 1000 Mbps,实际 940-980 Mbps +- **万兆以太网**:理论 10000 Mbps,实际 9400-9800 Mbps + +#### 无线网络: +- **Wi-Fi 4 (802.11n)**: + - 2.4GHz:理论 150-300 Mbps,实际 50-150 Mbps + - 5GHz:理论 300-450 Mbps,实际 100-250 Mbps + +- **Wi-Fi 5 (802.11ac)**: + - 理论 433-1733 Mbps,实际 200-800 Mbps + - 受距离和障碍物影响大 + +- **Wi-Fi 6 (802.11ax)**: + - 理论 600-9608 Mbps,实际 400-1200 Mbps + - 多设备性能更好 + +#### 互联网接入: +- **ADSL**:下行 8-24 Mbps,上行 1-3 Mbps +- **VDSL**:下行 50-100 Mbps,上行 10-20 Mbps +- **光纤到户**: + - 家庭:100-1000 Mbps,上下行对称或不对称 + - 企业:100-10000 Mbps,通常对称 +- **4G LTE**: + - 理论 100-300 Mbps,实际 20-80 Mbps + - 受信号强度和用户数影响 +- **5G**: + - 理论 1-10 Gbps,实际 100-1000 Mbps + - 毫米波可达更高速度 + +### C. 性能测试术语解释 + +#### 带宽相关: +- **带宽 (Bandwidth)**:网络传输数据的能力,单位 bps +- **吞吐量 (Throughput)**:实际达到的数据传输速率 +- **线速 (Line Rate)**:理论最大传输速率 +- **有效带宽 (Effective Bandwidth)**:考虑协议开销后的实际带宽 + +#### 延迟相关: +- **延迟 (Latency)**:数据从发送到接收的时间 +- **往返时间 (RTT)**:数据往返所需时间 +- **抖动 (Jitter)**:延迟的变化程度 +- **单向延迟 (One-way Delay)**:单向传输时间 + +#### 质量相关: +- **丢包率 (Packet Loss Rate)**:丢失的数据包比例 +- **乱序 (Out-of-Order)**:数据包到达顺序错误 +- **重复包 (Duplicate Packet)**:重复接收的数据包 +- **错误率 (Error Rate)**:包含错误的数据包比例 + +#### TCP相关: +- **重传 (Retransmission)**:TCP重新发送丢失的数据 +- **拥塞窗口 (Congestion Window)**:TCP根据网络状况调整的窗口 +- **慢启动 (Slow Start)**:TCP初始阶段指数增长窗口 +- **快速重传 (Fast Retransmit)**:收到3个重复ACK立即重传 + +### D. 推荐测试配置模板 + +#### 模板1:快速检查 +```json +{ + "name": "快速网络检查", + "server": "目标IP", + "port": 5201, + "duration": 10, + "parallel": 4, + "protocol": "tcp", + "interval": 1, + "expected_min_bandwidth": 500, + "expected_max_latency": 50, + "expected_max_loss": 0.1 +} +``` + +#### 模板2:全面评估 +```json +{ + "name": "全面网络评估", + "tests": [ + { + "name": "TCP单流基准", + "protocol": "tcp", + "parallel": 1, + "duration": 30 + }, + { + "name": "TCP多流性能", + "protocol": "tcp", + "parallel": 8, + "duration": 60 + }, + { + "name": "UDP质量测试", + "protocol": "udp", + "duration": 30, + "bandwidth": "100M", + "check": ["loss", "jitter"] + }, + { + "name": "双向压力测试", + "protocol": "tcp", + "parallel": 16, + "duration": 300, + "bidirectional": true + } + ], + "schedule": "每月执行", + "report": "详细报告" +} +``` + +#### 模板3:SLA验证 +```json +{ + "name": "SLA符合性验证", + "sla_requirements": { + "bandwidth": "≥ 95% of 1000 Mbps", + "latency": "≤ 50 ms", + "loss": "≤ 0.1%", + "availability": "≥ 99.9%" + }, + "test_frequency": "每小时", + "test_duration": 300, + "alert_thresholds": { + "warning": "80% of SLA", + "critical": "60% of SLA" + }, + "reporting": "实时仪表板 + 月度报告" +} +``` + +### E. 故障代码速查表 + +#### 连接错误: +- **ECONNREFUSED (111)**:连接被拒绝,检查服务器和防火墙 +- **ETIMEDOUT (110)**:连接超时,检查网络连通性 +- **EHOSTUNREACH (113)**:主机不可达,检查路由 +- **ENETUNREACH (101)**:网络不可达,检查网络配置 + +#### 性能问题: +- **低带宽**: + - 检查网卡协商状态 + - 检查中间设备限制 + - 检查系统资源使用 +- **高延迟**: + - 使用 traceroute 分析路径 + - 检查 QoS 配置 + - 检查网络拥塞 +- **高丢包**: + - 检查线缆质量 + - 检查设备错误计数 + - 检查 MTU 设置 + +#### 工具问题: +- **iperf3 未找到**:安装 iperf3 或检查 PATH +- **权限不足**:使用 sudo 或管理员权限 +- **端口被占用**:更改端口或停止占用程序 +- **内存不足**:减少并行流或测试时间 + +### F. 资源与参考 + +#### 官方资源: +- **iperf3 官网**:https://software.es.net/iperf/ +- **源代码**:https://github.com/esnet/iperf +- **文档**:https://iperf.fr/iperf-doc.php + +#### 学习资源: +- **网络性能测试指南**: + - https://www.ietf.org/rfc/rfc2544.txt (基准测试方法学) + - https://www.ietf.org/rfc/rfc6349.txt (TCP测试考虑) +- **TCP/IP 详解**:经典网络技术书籍 +- **网络诊断工具大全**:学习各种网络工具的使用 + +#### 社区支持: +- **GitHub Issues**:报告问题和功能请求 +- **Stack Overflow**:技术问题讨论 +- **网络技术论坛**:专业交流和学习 + +#### 相关工具: +- **ping**:基本连通性测试 +- **traceroute**:路径追踪 +- **mtr**:结合 ping 和 traceroute +- **tcpdump/Wireshark**:抓包分析 +- **netperf**:另一个网络性能测试工具 +- **iPerf2**:旧版本,有些场景仍在使用 + +--- + +## 结束语 + +### 工具的价值 +iperf3 图形化工具不仅仅是一个简单的界面包装,它是: +1. **学习工具**:帮助理解网络性能测试原理 +2. **诊断工具**:快速定位网络问题 +3. **验证工具**:确保网络服务符合预期 +4. **规划工具**:为网络扩容提供数据支持 +5. **监控工具**:持续跟踪网络质量变化 + +### 使用建议 +1. **从简单开始**:先使用默认配置,了解基本功能 +2. **逐步深入**:根据需要探索高级选项 +3. **记录实践**:记录每次测试的环境和结果 +4. **持续学习**:网络技术不断发展,保持学习 +5. **分享经验**:在社区分享使用经验和技巧 + +### 未来发展 +工具会持续更新和改进,计划中的功能包括: +1. **AI分析**:智能分析测试结果,自动给出建议 +2. **云集成**:深度集成云服务商的监控和测试功能 +3. **移动端**:开发手机App,随时随地进行测试 +4. **协作功能**:多人协作测试和分析 +5. **更多协议**:支持HTTP/3、QUIC等新协议 + +### 致谢 +感谢所有使用、测试和贡献的用户,特别是: +- 早期测试用户提供的宝贵反馈 +- GitHub社区的issue报告和讨论 +- 开源项目的贡献者们 +- 网络技术社区的分享和交流 + +### 联系我们 +虽然我们不提供私人邮箱支持,但您可以通过以下方式参与: +1. **GitHub Issues**:报告bug和请求功能 +2. **Pull Requests**:贡献代码和改进 +3. **文档贡献**:帮助完善文档 +4. **社区讨论**:分享使用经验 + +**记住**:最好的支持是公开的支持,您的问题和解决方案可以帮助更多人。 + +--- + +**版权声明** © 永久 杜玛 保留所有权利 + +**最后更新**:2024年1月 +**文档版本**:v1.0 +**工具版本**:iperf3 GUI v1.0.0 + +**注意**:本文档内容会随着工具更新而更新,请定期查看最新版本。 + +**免责声明**:本文档提供的信息仅供参考,作者不对因使用本文档或相关工具造成的任何损失负责。网络测试可能影响网络性能,请在适当的环境下进行测试。