在fifth.cc的基础上,源代码只设定了NewReno的策略,在此基础上,我对此进行改进,添加了Vegas和Cubic算法的对比分析,直接在终端打印输出三种算法的优劣
#include "ns3/applications-module.h" #include "ns3/core-module.h" #include "ns3/internet-module.h" #include "ns3/network-module.h" #include "ns3/point-to-point-module.h" #include <fstream> #include <iostream> #include <vector> #include <map> #include <iomanip> #include <algorithm> using namespace ns3; // 存储每种算法的统计信息 struct AlgorithmStats { std::string name; std::vector<double> timePoints; std::vector<uint32_t> cwndValues; double startTime; double endTime; uint32_t maxCwnd; uint32_t minCwnd; double avgCwnd; double finalCwnd; double growthRate; int dataPoints; AlgorithmStats() : name(""), startTime(0), endTime(0), maxCwnd(0), minCwnd(UINT32_MAX), avgCwnd(0), finalCwnd(0), growthRate(0), dataPoints(0) {} AlgorithmStats(const std::string& n) : name(n), startTime(0), endTime(0), maxCwnd(0), minCwnd(UINT32_MAX), avgCwnd(0), finalCwnd(0), growthRate(0), dataPoints(0) {} void AddDataPoint(double time, uint32_t cwnd) { timePoints.push_back(time); cwndValues.push_back(cwnd); if (dataPoints == 0) { startTime = time; } endTime = time; maxCwnd = std::max(maxCwnd, cwnd); minCwnd = std::min(minCwnd, cwnd); finalCwnd = cwnd; dataPoints++; double sum = 0; for (uint32_t val : cwndValues) { sum += val; } avgCwnd = sum / cwndValues.size(); if (cwndValues.size() >= 10) { double recentGrowth = 0; for (size_t i = cwndValues.size() - 10; i < cwndValues.size() - 1; i++) { double timeDiff = timePoints[i+1] - timePoints[i]; if (timeDiff > 0) { recentGrowth += (cwndValues[i+1] - cwndValues[i]) / timeDiff; } } growthRate = recentGrowth / 9.0; } } }; // 全局存储算法统计数据 std::map<std::string, AlgorithmStats> algorithmStats; // 为每个算法创建独立的回调函数 static void CwndChangeCubic(uint32_t oldCwnd, uint32_t newCwnd) { double currentTime = Simulator::Now().GetSeconds(); algorithmStats["Cubic"].AddDataPoint(currentTime, newCwnd); static double lastPrintTime = 0; if (currentTime - lastPrintTime >= 2.0) { std::cout << std::fixed << std::setprecision(2) << "Cubic @ " << currentTime << "s: " << "CWND=" << newCwnd << " bytes (" << std::setprecision(1) << newCwnd/1024.0 << " KB)" << std::endl; lastPrintTime = currentTime; } } static void CwndChangeNewReno(uint32_t oldCwnd, uint32_t newCwnd) { double currentTime = Simulator::Now().GetSeconds(); algorithmStats["NewReno"].AddDataPoint(currentTime, newCwnd); static double lastPrintTime = 0; if (currentTime - lastPrintTime >= 2.0) { std::cout << std::fixed << std::setprecision(2) << "NewReno @ " << currentTime << "s: " << "CWND=" << newCwnd << " bytes (" << std::setprecision(1) << newCwnd/1024.0 << " KB)" << std::endl; lastPrintTime = currentTime; } } static void CwndChangeVegas(uint32_t oldCwnd, uint32_t newCwnd) { double currentTime = Simulator::Now().GetSeconds(); algorithmStats["Vegas"].AddDataPoint(currentTime, newCwnd); static double lastPrintTime = 0; if (currentTime - lastPrintTime >= 2.0) { std::cout << std::fixed << std::setprecision(2) << "Vegas @ " << currentTime << "s: " << "CWND=" << newCwnd << " bytes (" << std::setprecision(1) << newCwnd/1024.0 << " KB)" << std::endl; lastPrintTime = currentTime; } } // 自定义应用类 class TcpCwndApp : public Application { public: TcpCwndApp(); virtual ~TcpCwndApp(); void Setup(Ptr<Socket> socket, Address address, uint32_t packetSize, DataRate dataRate); private: virtual void StartApplication(void); virtual void StopApplication(void); void SendPacket(void); Ptr<Socket> m_socket; Address m_peer; uint32_t m_packetSize; DataRate m_dataRate; EventId m_sendEvent; bool m_running; }; TcpCwndApp::TcpCwndApp() : m_socket(0), m_running(false) { } TcpCwndApp::~TcpCwndApp() { m_socket = 0; } void TcpCwndApp::Setup(Ptr<Socket> socket, Address address, uint32_t packetSize, DataRate dataRate) { m_socket = socket; m_peer = address; m_packetSize = packetSize; m_dataRate = dataRate; } void TcpCwndApp::StartApplication(void) { m_running = true; m_socket->Bind(); m_socket->Connect(m_peer); SendPacket(); } void TcpCwndApp::StopApplication(void) { m_running = false; if (m_sendEvent.IsRunning()) { Simulator::Cancel(m_sendEvent); } if (m_socket) { m_socket->Close(); } } void TcpCwndApp::SendPacket(void) { Ptr<Packet> packet = Create<Packet>(m_packetSize); m_socket->Send(packet); if (m_running) { Time tNext(Seconds(m_packetSize * 8 / static_cast<double>(m_dataRate.GetBitRate()))); m_sendEvent = Simulator::Schedule(tNext, &TcpCwndApp::SendPacket, this); } } // 运行单个算法的仿真 void RunAlgorithmSimulation(std::string algorithmName, std::string tcpType, Callback<void, uint32_t, uint32_t> cwndCallback) { std::cout << "\n" << std::string(60, '=') << std::endl; std::cout << " Starting " << algorithmName << " Simulation" << std::endl; std::cout << std::string(60, '=') << std::endl; // 初始化统计信息 algorithmStats[algorithmName] = AlgorithmStats(algorithmName); // 设置TCP算法类型 Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue(tcpType)); // 创建节点 NodeContainer nodes; nodes.Create(2); // 创建链路 PointToPointHelper pointToPoint; pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps")); pointToPoint.SetChannelAttribute("Delay", StringValue("2ms")); NetDeviceContainer devices; devices = pointToPoint.Install(nodes); // 安装协议栈 InternetStackHelper stack; stack.Install(nodes); // 分配IP地址 Ipv4AddressHelper address; address.SetBase("10.1.1.0", "255.255.255.252"); Ipv4InterfaceContainer interfaces = address.Assign(devices); // 创建socket并连接回调 uint16_t sinkPort = 8080; Address sinkAddress(InetSocketAddress(interfaces.GetAddress(1), sinkPort)); Ptr<Socket> tcpSocket = Socket::CreateSocket(nodes.Get(0), TcpSocketFactory::GetTypeId()); tcpSocket->TraceConnectWithoutContext("CongestionWindow", cwndCallback); // 创建自定义发送应用 Ptr<TcpCwndApp> app = CreateObject<TcpCwndApp>(); app->Setup(tcpSocket, sinkAddress, 1024, DataRate("1Mbps")); nodes.Get(0)->AddApplication(app); app->SetStartTime(Seconds(1.0)); app->SetStopTime(Seconds(20.0)); // 创建接收端 PacketSinkHelper sink("ns3::TcpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), sinkPort)); ApplicationContainer sinkApps = sink.Install(nodes.Get(1)); sinkApps.Start(Seconds(0.0)); sinkApps.Stop(Seconds(20.0)); // 运行仿真 Simulator::Stop(Seconds(20)); Simulator::Run(); Simulator::Destroy(); // 显示该算法的简要统计 AlgorithmStats& stats = algorithmStats[algorithmName]; std::cout << "\n" << algorithmName << " Simulation Complete:" << std::endl; std::cout << std::string(40, '-') << std::endl; std::cout << std::fixed << std::setprecision(2); std::cout << " Data Points: " << std::setw(8) << stats.dataPoints << std::endl; std::cout << " Time Range: " << std::setw(8) << stats.startTime << " - " << stats.endTime << " s" << std::endl; std::cout << " Duration: " << std::setw(8) << (stats.endTime - stats.startTime) << " s" << std::endl; std::cout << " Max CWND: " << std::setw(8) << stats.maxCwnd << " bytes (" << std::setprecision(1) << stats.maxCwnd/1024.0 << " KB)" << std::endl; std::cout << " Min CWND: " << std::setw(8) << stats.minCwnd << " bytes (" << std::setprecision(1) << stats.minCwnd/1024.0 << " KB)" << std::endl; std::cout << " Average CWND: " << std::setw(8) << std::setprecision(0) << stats.avgCwnd << " bytes (" << std::setprecision(1) << stats.avgCwnd/1024.0 << " KB)" << std::endl; std::cout << " Final CWND: " << std::setw(8) << std::setprecision(0) << stats.finalCwnd << " bytes (" << std::setprecision(1) << stats.finalCwnd/1024.0 << " KB)" << std::endl; std::cout << " Growth Rate: " << std::setw(8) << std::setprecision(0) << stats.growthRate << " bytes/s" << std::endl; } // 打印详细的对比表格 void PrintComparisonTable() { std::cout << "\n" << std::string(80, '=') << std::endl; std::cout << " TCP CONGESTION CONTROL ALGORITHMS COMPARISON" << std::endl; std::cout << std::string(80, '=') << std::endl; std::cout << " Network Conditions: 5Mbps bandwidth, 2ms delay" << std::endl; std::cout << " Application: 1Mbps data rate, 1024 byte packets" << std::endl; std::cout << " Simulation Time: 20 seconds per algorithm" << std::endl; std::cout << std::string(80, '=') << std::endl; // 表头 std::cout << std::left << std::setw(12) << "Algorithm" << std::setw(12) << "Data Pts" << std::setw(12) << "Duration(s)" << std::setw(15) << "Max CWND(KB)" << std::setw(15) << "Avg CWND(KB)" << std::setw(15) << "Final CWND(KB)" << std::setw(15) << "Growth(b/s)" << std::endl; std::cout << std::string(80, '-') << std::endl; // 数据行 for (const auto& pair : algorithmStats) { const AlgorithmStats& stats = pair.second; std::cout << std::left << std::setw(12) << stats.name << std::right << std::setw(10) << stats.dataPoints << std::setw(12) << std::fixed << std::setprecision(1) << (stats.endTime - stats.startTime) << std::setw(15) << std::setprecision(1) << stats.maxCwnd/1024.0 << std::setw(15) << std::setprecision(1) << stats.avgCwnd/1024.0 << std::setw(15) << std::setprecision(1) << stats.finalCwnd/1024.0 << std::setw(15) << std::setprecision(0) << stats.growthRate << std::endl; } std::cout << std::string(80, '=') << std::endl; } // 打印性能排名 void PrintPerformanceRankings() { std::cout << "\n" << std::string(60, '=') << std::endl; std::cout << " PERFORMANCE RANKINGS" << std::endl; std::cout << std::string(60, '=') << std::endl; // 按最大CWND排名 std::vector<std::pair<std::string, double>> maxCwndRanking; for (const auto& pair : algorithmStats) { maxCwndRanking.push_back({pair.first, pair.second.maxCwnd}); } std::sort(maxCwndRanking.begin(), maxCwndRanking.end(), [](const auto& a, const auto& b) { return a.second > b.second; }); std::cout << "\n1. Maximum CWND (Aggressiveness):" << std::endl; std::cout << " Rank | Algorithm | Max CWND (KB)" << std::endl; std::cout << " -----+-----------+--------------" << std::endl; for (size_t i = 0; i < maxCwndRanking.size(); i++) { std::cout << " " << std::setw(4) << i+1 << " | " << std::setw(9) << maxCwndRanking[i].first << " | " << std::fixed << std::setprecision(1) << std::setw(10) << maxCwndRanking[i].second/1024.0 << " KB" << std::endl; } // 按平均CWND排名 std::vector<std::pair<std::string, double>> avgCwndRanking; for (const auto& pair : algorithmStats) { avgCwndRanking.push_back({pair.first, pair.second.avgCwnd}); } std::sort(avgCwndRanking.begin(), avgCwndRanking.end(), [](const auto& a, const auto& b) { return a.second > b.second; }); std::cout << "\n2. Average CWND (Stable Throughput):" << std::endl; std::cout << " Rank | Algorithm | Avg CWND (KB)" << std::endl; std::cout << " -----+-----------+--------------" << std::endl; for (size_t i = 0; i < avgCwndRanking.size(); i++) { std::cout << " " << std::setw(4) << i+1 << " | " << std::setw(9) << avgCwndRanking[i].first << " | " << std::fixed << std::setprecision(1) << std::setw(10) << avgCwndRanking[i].second/1024.0 << " KB" << std::endl; } // 按增长率排名 std::vector<std::pair<std::string, double>> growthRanking; for (const auto& pair : algorithmStats) { growthRanking.push_back({pair.first, pair.second.growthRate}); } std::sort(growthRanking.begin(), growthRanking.end(), [](const auto& a, const auto& b) { return a.second > b.second; }); std::cout << "\n3. Growth Rate (Responsiveness):" << std::endl; std::cout << " Rank | Algorithm | Growth Rate (bytes/s)" << std::endl; std::cout << " -----+-----------+----------------------" << std::endl; for (size_t i = 0; i < growthRanking.size(); i++) { std::cout << " " << std::setw(4) << i+1 << " | " << std::setw(9) << growthRanking[i].first << " | " << std::fixed << std::setprecision(0) << std::setw(15) << growthRanking[i].second << " bytes/s" << std::endl; } // 综合评分 std::cout << "\n4. Overall Performance Score:" << std::endl; std::cout << " (Score = 0.4*MaxCWND + 0.4*AvgCWND + 0.2*GrowthRate)" << std::endl; std::cout << " Algorithm | Score | Normalized" << std::endl; std::cout << " ----------+-------+-----------" << std::endl; std::vector<std::pair<std::string, double>> overallScores; double maxScore = 0; for (const auto& pair : algorithmStats) { const AlgorithmStats& stats = pair.second; double score = 0.4 * (stats.maxCwnd / 1024.0) + 0.4 * (stats.avgCwnd / 1024.0) + 0.2 * (stats.growthRate / 1000.0); overallScores.push_back({pair.first, score}); maxScore = std::max(maxScore, score); } std::sort(overallScores.begin(), overallScores.end(), [](const auto& a, const auto& b) { return a.second > b.second; }); for (const auto& score : overallScores) { std::cout << " " << std::setw(9) << score.first << " | " << std::fixed << std::setprecision(2) << std::setw(5) << score.second << " | " << std::setprecision(1) << std::setw(7) << (score.second / maxScore * 100) << "%" << std::endl; } } int main(int argc, char *argv[]) { std::cout << "\n" << std::string(70, '*') << std::endl; std::cout << " TCP CONGESTION CONTROL ALGORITHM COMPARISON TOOL" << std::endl; std::cout << std::string(70, '*') << std::endl; // 运行每种算法的仿真 - 使用Cubic、NewReno、Vegas std::cout << "\nRunning Cubic simulation..." << std::endl; RunAlgorithmSimulation("Cubic", "ns3::TcpCubic", MakeCallback(&CwndChangeCubic)); std::cout << "\nRunning NewReno simulation..." << std::endl; RunAlgorithmSimulation("NewReno", "ns3::TcpNewReno", MakeCallback(&CwndChangeNewReno)); std::cout << "\nRunning Vegas simulation..." << std::endl; RunAlgorithmSimulation("Vegas", "ns3::TcpVegas", MakeCallback(&CwndChangeVegas)); // 打印对比结果 PrintComparisonTable(); PrintPerformanceRankings(); // 最终总结 std::cout << "\n" << std::string(70, '=') << std::endl; std::cout << " FINAL SUMMARY" << std::endl; std::cout << std::string(70, '=') << std::endl; // 找出最佳算法 std::string bestMaxCwnd, bestAvgCwnd, bestGrowth; double maxMaxCwnd = 0, maxAvgCwnd = 0, maxGrowth = 0; for (const auto& pair : algorithmStats) { const AlgorithmStats& stats = pair.second; if (stats.maxCwnd > maxMaxCwnd) { maxMaxCwnd = stats.maxCwnd; bestMaxCwnd = stats.name; } if (stats.avgCwnd > maxAvgCwnd) { maxAvgCwnd = stats.avgCwnd; bestAvgCwnd = stats.name; } if (stats.growthRate > maxGrowth) { maxGrowth = stats.growthRate; bestGrowth = stats.name; } } std::cout << "\nBest Algorithm for Each Metric:" << std::endl; std::cout << "--------------------------------" << std::endl; std::cout << "Maximum CWND (Aggressiveness): " << bestMaxCwnd << " (" << std::fixed << std::setprecision(1) << maxMaxCwnd/1024.0 << " KB)" << std::endl; std::cout << "Average CWND (Stability): " << bestAvgCwnd << " (" << std::fixed << std::setprecision(1) << maxAvgCwnd/1024.0 << " KB)" << std::endl; std::cout << "Growth Rate (Responsiveness): " << bestGrowth << " (" << std::fixed << std::setprecision(0) << maxGrowth << " bytes/s)" << std::endl; // 算法特性分析 std::cout << "\nAlgorithm Characteristics:" << std::endl; std::cout << "---------------------------" << std::endl; std::cout << "Cubic: Linux默认算法,高带宽延迟积网络表现好" << std::endl; std::cout << "NewReno: 标准TCP算法,稳定性好" << std::endl; std::cout << "Vegas: 基于延迟的算法,避免拥塞,但可能不公平" << std::endl; std::cout << "\n" << std::string(70, '*') << std::endl; std::cout << " COMPARISON COMPLETE" << std::endl; std::cout << std::string(70, '*') << std::endl; return 0; }上述代码是直接的可执行文件,运行之后结果为: