环境:VMware17.5 Ubuntu20.04
目的:在fifth.cc基础上设置TCP拥塞控制算法,通过创建一个简单的网络拓扑(两个节点和点对点连接),并在节点上安装应用程序进行数据流传输,同时利用回调函数来监控拥塞窗口的变化和丢包事件。
1.复制fifth.cc文件,命名为fifth-copy.cc
确保当前位于fifth.cc文件所在路径,如:
cd ~/tarballs/ns-allinone-3.36.1/ns-3.36.1/examples/tutorial
执行复制命令:
确认是否复制成功:
ls //应该能看到
fifth-copy.cc
文件出现在文件列表中
2.修改fifth-copy代码
(完整代码在最后)
使用vi/vim命令进行编辑修改
头文件中增加以下代码:
#include "ns3/tcp-congestion-ops.h" // 包含自定义的 TCP 拥塞控制算法头文件
使用自定义的拥塞控制算法 更改为对应算法:
// 设置自定义的拥塞控制算法
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::TcpVegas")); // 使用自定义的拥塞控制算法
3.修改CMakeLists.txt 文件并保存(关键)
(否则编译运行以后会报错:Target to build does not exist: examples/tutorial/fifth-copy.cc)
将fifth-copy.cc文件注册到构建系统中。虽然 fifth.cc
文件已经被注册,但如果需要单独编译和运行fifth-copy.cc,必须将其添加到 CMakeLists.txt 文件中。
CMakeLists.txt 路径:examples/tutorial/CMakeLists.txt
在CMakeLists.txt最后添加以下代码:
build_example(
NAME fifth-copy
SOURCE_FILES fifth-copy.cc
LIBRARIES_TO_LINK
${libcore}
${libpoint-to-point}
${libinternet}
${libapplications}
)
4.重新配置并编译项目
每次修改CMakeLists.txt 后,需要重新运行配置和编译命令:
cd ~/tarballs/ns-allinone-3.36.1/ns-3.36.1
./ns3 configure
./ns3 build //也可以直接编译fifth-copy ./ns3 build examples/tutorial/fifth-copy
5.运行fifth-copy
./ns3 run examples/tutorial/fifth-copy
此时即可得到对应数据点(时间点和窗口大小以及丢包情况)
6.结果可视化
同ffth.cc程序一样,用gnuplot进行结果可视化
具体见:NS3学习------运行第五个(fifth.cc)示例(附fifth.cc源代码_ns3运行tutorial-CSDN博客
7.生成窗口图如下
完整源码:
cpp
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-module.h"
#include "tutorial-app.h"
#include "ns3/tcp-congestion-ops.h" // 包含自定义的 TCP 拥塞控制算法头文件
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("FifthScriptExample");
// ===========================================================================
// 你的网络拓扑和应用程序代码...
// ===========================================================================
static void
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
}
static void
RxDrop (Ptr<const Packet> p)
{
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
}
int
main (int argc, char *argv[])
{
CommandLine cmd (__FILE__);
cmd.Parse (argc, argv);
// 设置自定义的拥塞控制算法
Config::SetDefault ("ns3::TcpL4Protocol::SocketType", StringValue ("ns3::TcpVegas")); // 使用自定义的拥塞控制算法
Config::SetDefault ("ns3::TcpSocket::InitialCwnd", UintegerValue (1));
Config::SetDefault ("ns3::TcpL4Protocol::RecoveryType", TypeIdValue (TypeId::LookupByName ("ns3::TcpClassicRecovery")));
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;
stack.Install (nodes);
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.252");
Ipv4InterfaceContainer interfaces = address.Assign (devices);
uint16_t sinkPort = 8080;
Address sinkAddress (InetSocketAddress (interfaces.GetAddress (1), sinkPort));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
sinkApps.Start (Seconds (0.));
sinkApps.Stop (Seconds (20.));
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndChange));
Ptr<TutorialApp> app = CreateObject<TutorialApp> ();
app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
nodes.Get (0)->AddApplication (app);
app->SetStartTime (Seconds (1.));
app->SetStopTime (Seconds (20.));
devices.Get (1)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&RxDrop));
Simulator::Stop (Seconds (20));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}