背景

某日发现网络每半小时会出现两到三次非常高的延迟,就打算测试一下是什么问题

发现主流的测试方法是ping与tracert,直接使用命令不太方便统计与寻找问题

所以找到了好用的图形化软件来使用,分别是

https://github.com/sn4k3/NetSonar

https://github.com/White-Tiger/WinMTR

NetSonar是基于ping命令的图形化测试工具

WinMTR是基于tracert命令的图形化测试工具

两者都是开源软件,均可导出测试数据

NetSonar主要使用的是ICMP包,可同时多个ip进行测试,可自定义每ping的间隔与包大小等等

有个小缺点,虽然csv文件数据间使用逗号或者分号都可以,这里导出的数据用的分号

但是wps读取时是按逗号读取的,分号不识别为分隔符,所以需要手动替换全文的分号为逗号,或者在wps设置里改动

WinMTR主要使用的也是ICMP包,但是不会保存每一次的数据,最后的导出结果只具有参考性,中间链路节点丢包严重可能是服务策略对测试包优先级不高,优先为业务数据服务了

对NetSonar导出ping结果折线图可视化

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题

# 1. 读取 CSV 文件
df = pd.read_csv("icmp-public1.alidns.com-17-10-2025-21-00-17.csv")

# 2. 转换时间格式
df["SentDateTime"] = pd.to_datetime(df["SentDateTime"])

# 3. 处理 Time 字段,把 "∞" 转换为 NaN
df["Time"] = pd.to_numeric(df["Time"], errors="coerce")

# 4. 统计分析
success_df = df[df["IsSucceeded"] == True]
fail_df = df[df["IsSucceeded"] == False]

avg_time = success_df["Time"].mean()
min_time = success_df["Time"].min()
max_time = success_df["Time"].max()
loss_rate = len(fail_df) / len(df) * 100  # 丢包率 %

# 5. 绘图
plt.figure(figsize=(12, 6))
plt.plot(df["SentDateTime"], df["Time"], marker="o", label="响应时间 (ms)")

# 标注超时的点
plt.scatter(fail_df["SentDateTime"],
            [max_time * 1.1] * len(fail_df),  # 在图上方显示
            color="red", marker="x", s=80, label="超时")

# 6. 美化
plt.title("Ping 数据分析")
plt.xlabel("时间")
plt.ylabel("响应时间 (ms)")
plt.legend()
plt.grid(True)

# 设置横坐标日期格式,包含月份信息
date_format = DateFormatter('%m/%d %H:%M')  # 格式为 月/日 小时:分钟
plt.gca().xaxis.set_major_formatter(date_format)
plt.xticks(rotation=45)  # 旋转45度

# 7. 在图表上写统计信息
stats_text = (
    f"平均延迟: {avg_time:.2f} ms\n"
    f"最小延迟: {min_time} ms\n"
    f"最大延迟: {max_time} ms\n"
    f"丢包率: {loss_rate:.2f}%"
)
plt.text(0.02, 0.95, stats_text, transform=plt.gca().transAxes,
         verticalalignment="top", bbox=dict(facecolor="white", alpha=0.7))

plt.tight_layout()
plt.show()