NS3-cubic/Vegas/NewReno对比分析
·
在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;
}
上述代码是直接的可执行文件,运行之后结果为:


更多推荐
所有评论(0)