在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;
}

上述代码是直接的可执行文件,运行之后结果为:

更多推荐