目 录CONTENT

文章目录

例程-seventh.cc

Rho
Rho
2023-08-27 / 0 评论 / 0 点赞 / 33 阅读 / 7727 字
这段代码是一个使用ns-3网络模拟器的示例程序,用于模拟两个节点之间的TCP数据流,并跟踪拥塞窗口的变化。

代码的主要功能包括:

  • 创建两个节点和一个点对点的网络连接。
  • 配置网络设备的属性,如数据传输速率和延迟。
  • 安装Internet协议栈和TCP应用。
  • 创建一个PacketSink应用作为接收方,用于接收来自源节点的TCP流量。
  • 创建一个自定义的TutorialApp应用作为发送方,用于生成TCP流量并发送到接收方。
  • 跟踪拥塞窗口的变化,并将数据写入文件。
  • 跟踪接收方丢弃的数据包,并将数据写入PCAP文件。
  • 使用GnuplotHelper绘制数据包字节计数随时间的变化图表。
  • 使用FileHelper将数据包字节计数随时间的变化写入文件。
  • 运行模拟器并销毁模拟环境。

总体而言,该代码用于演示如何在ns-3网络模拟器中创建TCP数据流,并跟踪拥塞窗口的变化以及数据包的丢失情况。

//         node 0                 node 1
//   +----------------+    +----------------+
//   |    ns-3 TCP    |    |    ns-3 TCP    |
//   +----------------+    +----------------+
//   |    10.1.1.1    |    |    10.1.1.2    |
//   +----------------+    +----------------+
//   | point-to-point |    | point-to-point |
//   +----------------+    +----------------+
//           |                     |
//           +---------------------+
//                5 Mbps, 2 ms
#include "tutorial-app.h" // 包含自定义的tutorial-app头文件

#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 "ns3/stats-module.h" // 包含统计模块头文件

#include <fstream> // 包含文件流头文件

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("SeventhScriptExample"); // 定义日志组件

// 回调函数:拥塞窗口变化
static void
CwndChange(Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
{
    NS_LOG_UNCOND(Simulator::Now().GetSeconds() << "\t" << newCwnd); // 记录拥塞窗口变化
    *stream->GetStream() << Simulator::Now().GetSeconds() << "\t" << oldCwnd << "\t" << newCwnd
                         << std::endl; // 将拥塞窗口变化写入输出流
}

// 回调函数:接收端丢包
static void
RxDrop(Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
{
    NS_LOG_UNCOND("RxDrop at " << Simulator::Now().GetSeconds()); // 记录数据包丢失发生的时间
    file->Write(Simulator::Now(), p); // 将丢失的数据包写入PCAP文件
}

int
main(int argc, char* argv[])
{
    bool useV6 = false;

    CommandLine cmd(__FILE__);
    cmd.AddValue("useIpv6", "Use Ipv6", useV6);
    cmd.Parse(argc, argv);

    NodeContainer nodes; // 创建节点容器
    nodes.Create(2); // 创建两个节点

    PointToPointHelper pointToPoint; // 创建点对点网络连接助手
    pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps")); // 设置链路数据速率
    pointToPoint.SetChannelAttribute("Delay", StringValue("2ms")); // 设置链路延迟

    NetDeviceContainer devices; // 创建网络设备容器
    devices = pointToPoint.Install(nodes); // 安装网络设备

    Ptr<RateErrorModel> em = CreateObject<RateErrorModel>(); // 创建错误模型
    em->SetAttribute("ErrorRate", DoubleValue(0.00001)); // 设置错误率
    devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(em)); // 设置接收端的错误模型

    InternetStackHelper stack; // 创建Internet协议栈助手
    stack.Install(nodes); // 安装Internet协议栈

    uint16_t sinkPort = 8080; // 数据包接收器监听的端口号
    Address sinkAddress; // 接收器地址
    Address anyAddress; // 任意地址
    std::string probeType; // 探测类型
    std::string tracePath; // 跟踪路径
    if (useV6 == false)
    {
        Ipv4AddressHelper address; // 创建IPv4地址助手
        address.SetBase("10.1.1.0", "255.255.255.0"); // 设置IPv4地址范围
        Ipv4InterfaceContainer interfaces = address.Assign(devices); // 分配IPv4地址给设备
        sinkAddress = InetSocketAddress(interfaces.GetAddress(1), sinkPort); // 获取接收器地址
        anyAddress = InetSocketAddress(Ipv4Address::GetAny(), sinkPort); // 获取任意地址
        probeType = "ns3::Ipv4PacketProbe"; // 设置探测类型为IPv4
        tracePath = "/NodeList/*/$ns3::Ipv4L3Protocol/Tx"; // 设置跟踪路径
    }
    else
    {
        Ipv6AddressHelper address; // 创建IPv6地址助手
        address.SetBase("2001:0000:f00d:cafe::", Ipv6Prefix(64)); // 设置IPv6地址范围
        Ipv6InterfaceContainer interfaces = address.Assign(devices); // 分配IPv6地址给设备
        sinkAddress = Inet6SocketAddress(interfaces.GetAddress(1), sinkPort); // 获取接收器地址
        anyAddress = Inet6SocketAddress(Ipv6Address::GetAny(), sinkPort); // 获取任意地址
        probeType = "ns3::Ipv6PacketProbe"; // 设置探测类型为IPv6
        tracePath = "/NodeList/*/$ns3::Ipv6L3Protocol/Tx"; // 设置跟踪路径
    }

    PacketSinkHelper packetSinkHelper(probeType, anyAddress); // 创建数据包接收器助手
    ApplicationContainer sinkApps = packetSinkHelper.Install(nodes.Get(1)); // 在接收端节点安装数据包接收器
    sinkApps.Start(Seconds(0.0)); // 启动数据包接收器
    sinkApps.Stop(Seconds(20.0)); // 停止数据包接收器

    Ptr<Socket> ns3TcpSocket = Socket::CreateSocket(nodes.Get(0), TcpSocketFactory::GetTypeId());   // 创建一个TCP套接字,并将其指针赋值给ns3TcpSocket变量

    Ptr<TutorialApp> app = CreateObject<TutorialApp>();     // 创建TutorialApp对象,并将其指针赋值给app变量

    app->Setup(ns3TcpSocket, sinkAddress, 1040, 1000, DataRate("1Mbps"));   // 调用TutorialApp的Setup函数,设置应用程序的参数
    nodes.Get(0)->AddApplication(app);  // 将应用程序app添加到节点0
    app->SetStartTime(Seconds(1.)); // 设置应用程序的开始时间为1秒
    app->SetStopTime(Seconds(20.)); // 设置应用程序的停止时间为20秒

    AsciiTraceHelper asciiTraceHelper;  // 创建AsciiTraceHelper对象,用于生成ASCII跟踪文件

    Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream("seventh.cwnd");    // 创建输出流,用于记录拥塞窗口变化,并将其指针赋值给stream变量

    ns3TcpSocket->TraceConnectWithoutContext("CongestionWindow",
                                             MakeBoundCallback(&CwndChange, stream));   // 将拥塞窗口变化与输出流进行连接,当拥塞窗口变化时,调用CwndChange函数进行记录

    PcapHelper pcapHelper;  // 创建PcapHelper对象,用于生成PCAP文件
    Ptr<PcapFileWrapper> file =
        pcapHelper.CreateFile("seventh.pcap", std::ios::out, PcapHelper::DLT_PPP);  // 创建PCAP文件,用于记录丢失的数据包,并将其指针赋值给file变量

    devices.Get(1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback(&RxDrop, file));  // 将数据包丢失事件与PCAP文件进行连接,当数据包丢失时,调用RxDrop函数进行记录

    GnuplotHelper plotHelper;   // 创建GnuplotHelper对象,用于绘制图表

    plotHelper.ConfigurePlot("seventh-packet-byte-count",
                             "Packet Byte Count vs. Time",
                             "Time (Seconds)",
                             "Packet Byte Count");  // 配置图表的属性,包括文件名前缀、标题、x轴和y轴标签

    plotHelper.PlotProbe(probeType,
                         tracePath,
                         "OutputBytes",
                         "Packet Byte Count",
                         GnuplotAggregator::KEY_BELOW); // 绘制指定的探测类型的数据,将其与跟踪源路径和输出字节计数进行连接,指定数据系列标签和图表的格式

    FileHelper fileHelper;  // 创建FileHelper对象,用于写入文件

    fileHelper.ConfigureFile("seventh-packet-byte-count", FileAggregator::FORMATTED);   // 配置要写入的文件的属性和格式化方式

    fileHelper.Set2dFormat("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");  // 设置文件的格式化输出标签
    fileHelper.WriteProbe(probeType, tracePath, "OutputBytes"); // 写入指定的探测类型的数据到文件
    Simulator::Stop(Seconds(20));   // 设置仿真的停止时间为20秒
    Simulator::Run();   // 运行仿真
    Simulator::Destroy();   // 销毁仿真环境


    return 0;
    // 返回0,表示程序执行成功
}
0

评论区