NS3新手求助:如何编写代码绘制吞吐量/丢包率随时间变化曲线
刚接触NS3就要搞定作业里的吞吐量和丢包率曲线,确实有点摸不着头脑对吧?别担心,咱们从修改你已经在跑的fifth.cc入手,一步步搞定数据收集和绘图!
实现TCP吞吐量&丢包率随时间变化曲线的完整步骤
一、NS3端的数据收集(基于fifth.cc修改)
咱们直接在现有代码上添加数据追踪逻辑,不用从零写新脚本。
1. 收集吞吐量数据(Sink端统计)
吞吐量的核心是每隔固定时间统计Sink接收到的总字节数,再转换成Mbps单位(公式:(字节数*8)/(1024*1024*时间间隔))。
步骤代码:
- 先在文件开头添加全局变量和文件操作头文件:
#include <fstream> #include <iostream> using namespace std; // 吞吐量统计相关变量 ofstream throughputFile; double lastStatTime = 0.0; uint64_t lastRxBytes = 0;
- 添加追踪Sink接收数据的回调函数:
void RecordThroughput(Ptr<const Packet> packet, const Address& from) { double currentTime = Simulator::Now().GetSeconds(); uint64_t currentRxBytes = packet->GetSize(); // 每隔1秒统计一次吞吐量(可根据需求调整间隔) if (currentTime - lastStatTime >= 1.0) { double throughputMbps = (currentRxBytes - lastRxBytes) * 8.0 / (1024 * 1024 * (currentTime - lastStatTime)); throughputFile << currentTime << " " << throughputMbps << endl; // 更新统计基准 lastStatTime = currentTime; lastRxBytes = currentRxBytes; } }
- 在创建TCP Sink的代码段,绑定这个回调:
// 找到原代码中创建sink的部分,添加绑定逻辑 Ptr<PacketSink> sink = CreateObject<PacketSink>(); sink->SetAttribute("Protocol", TypeIdValue(TcpSocketFactory::GetTypeId())); nodes.Add(sink); sink->SetNode(nodes.Get(1)); // 绑定接收数据的追踪回调 sink->TraceConnectWithoutContext("Rx", MakeCallback(&RecordThroughput));
- 在
Simulator::Run()前打开输出文件,运行结束后关闭:
// 打开吞吐量数据文件 throughputFile.open("throughput_data.txt"); throughputFile << "Time(s) Throughput(Mbps)" << endl; // 可选表头 Simulator::Run(); // 关闭文件 throughputFile.close(); Simulator::Destroy();
2. 收集丢包数据(配合你的MATLAB处理)
如果你已经有丢包事件数据,这部分可以按需补充;如果需要更精准的丢包统计,咱们可以在NS3里追踪链路丢包:
- 添加丢包统计的全局变量和文件:
ofstream lossFile; uint64_t totalLost = 0; double lastLossStatTime = 0.0;
- 添加丢包追踪的回调函数:
void RecordPacketLoss(Ptr<const Packet> packet, const Address& from) { double currentTime = Simulator::Now().GetSeconds(); totalLost++; // 每隔1秒统计累计丢包数(也可以直接记录每个丢包的时间点) if (currentTime - lastLossStatTime >= 1.0) { lossFile << currentTime << " " << totalLost << endl; lastLossStatTime = currentTime; } // 若需记录单个丢包时间,直接写:lossFile << currentTime << " 1" << endl; }
- 绑定到点对点链路的接收端设备:
// 找到原代码中创建点对点设备的部分 NetDeviceContainer devices = pointToPoint.Install(nodes); // 绑定丢包追踪到接收端设备 devices.Get(1)->TraceConnectWithoutContext("Drop", MakeCallback(&RecordPacketLoss));
- 同样在Run前打开文件,结束后关闭:
lossFile.open("loss_data.txt"); lossFile << "Time(s) TotalLostPackets" << endl; Simulator::Run(); lossFile.close(); Simulator::Destroy();
二、用MATLAB绘制曲线
现在你已经拿到throughput_data.txt和丢包相关数据,直接用MATLAB处理绘图即可。
1. 绘制吞吐量曲线
% 加载吞吐量数据 data = load('throughput_data.txt'); time = data(:, 1); throughput = data(:, 2); figure; plot(time, throughput, 'b-', 'LineWidth', 1.5); xlabel('时间 (s)'); ylabel('吞吐量 (Mbps)'); title('TCP吞吐量随时间变化曲线'); grid on; set(gca, 'FontSize', 10);
2. 绘制丢包率曲线
假设你已经有丢包事件时间或每秒丢包数,结合发送数据包数计算丢包率(丢包率=(每秒丢包数/每秒发送数)*100%):
% 加载丢包事件数据(每行一个丢包时间) loss_events = load('loss_events.txt'); % 加载发送数据统计(每行是时间+每秒发送包数) send_stats = load('send_data.txt'); % 统计每秒丢包数 time_edges = 0:1:max(send_stats(:,1)); [loss_counts, ~] = histcounts(loss_events, time_edges); loss_per_sec = loss_counts(1:end-1); time_axis = 0.5:1:max(send_stats(:,1))-0.5; % 取每秒中间时间点 % 计算丢包率 loss_rate = (loss_per_sec ./ send_stats(:,2)) * 100; figure; plot(time_axis, loss_rate, 'r-', 'LineWidth', 1.5); xlabel('时间 (s)'); ylabel('丢包率 (%)'); title('TCP丢包率随时间变化曲线'); grid on; set(gca, 'FontSize', 10);
三、小提示
- 统计间隔可以灵活调整:比如把1秒改成0.5秒,只需要修改回调里的时间判断条件即可。
- 若拓扑不是点对点,丢包可能发生在其他位置(比如无线节点),需要调整绑定追踪的对象(比如无线NetDevice的Drop事件)。
- 单位转换别搞错:字节转比特要乘8,转Mbps要除以
1024*1024(因为1Mbps=1024*1024 bps)。
内容的提问来源于stack exchange,提问作者Mavimo
相关产品推荐
相关产品推荐

