NS-3例程注解与拓展
准备
运行准备
要运行自己的脚本,只需把脚本放到scratch目录下,通过waf脚本就会被编译。
cp examples/tutorial/first.cc scratch/myfirst.cc
使用waf命令来编译自己的第一个实例脚本:
sudo ./waf
运行这个例子
sudo ./waf --run scratch/myfirst
本文均在代码中加入输出XMl文件相应的语句,从而利用NetAnim生成可视化的动画。
在这里插入代码片
概览
NS-3给出的例程在 XXX 目录中,其中first-third.cc均是关于构建网络拓扑结构的。
其中:
- first 是 :点到点的网络模型(P + P)
- second 是 :点到以太网的网络模型 (P + LAN )
- third:是 :WIFI到以太网的网络模型 (WIFI + LAN)
最后我自己给出的网络则是:
- myfourth.cc:是 :以太网到以太网的网络模型 ( LAN + LAN)
分析
first.cc
网络拓扑如下:
// Default Network Topology
//
// 10.1.1.0
// n0 -------------- n1
// point-to-point
//
//
源码分析:
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/netanim-module.h"
using namespace ns3;
// 定义一个日志组件
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
int
main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
//设置时间精度,只能设置一次,因为动态设置对内存需求大,
//因此一旦设置,就会释放内存,如果不设置,使用默认值ns(纳秒)
Time::SetResolution (Time::NS);
// 使两个日志组件生效,内置在EchoClient和EchoServer应用中
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
// 创建节点对象,并且在内部存储Node对象指针
NodeContainer nodes;
nodes.Create (2);
// 设置网络设备和信道属性
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer devices;
// install方法将设备安装到节点中
//在NodeContainer中的每一个Node创建一个PointToPointNetDevice,
devices = pointToPoint.Install (nodes);
// ***为计算机每个node中安装协议栈
InternetStackHelper stack;
stack.Install (nodes);
Ipv4AddressHelper address; // 声明了一个地址助手对象
address.SetBase ("10.1.1.0", "255.255.255.0"); //从10.1.1.0 开始 以子网掩码为 255.255.255.0 分配地址
//ns-3中使用interface来在device及IP地址间建立关联
Ipv4InterfaceContainer interfaces = address.Assign (devices); // 完成了真正的地址配置
// ***下面安装应用层
UdpEchoServerHelper echoServer (9); // 服务器端
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0)); // echoServer 在 1s 时开始
serverApps.Stop (Seconds (10.0)); //echoServer 在 10s时结束,可选可不选
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);//使用Node1的地址及端口号(9)初始化辅助对象
echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); // 能发送的最大数据分组个数
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); // 两个数据分组之间要等的时间
echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); // 每个数据分组的大小
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));//同上,开始时间
clientApps.Stop (Seconds (10.0));
// 以下三行用于生成可视化文件
AnimationInterface anim("first.xml"); //
anim.SetConstantPosition(nodes.Get(0), 1.0, 2.0);
anim.SetConstantPosition(nodes.Get(1), 2.0, 3.0);
Simulator::Run (); // 启动模拟器
Simulator::Destroy (); // 销毁任务
return 0;
}
second.cc
网络拓扑如下:
> // Default Network Topology
//
// 10.1.1.0
// n0 -------------- n1 n2 n3 n4
// point-to-point | | | |
// ================
// LAN 10.1.2.0
源码分析:
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"
using namespace ns3;
// 定义一个日志组件
NS_LOG_COMPONENT_DEFINE("SecondScriptExample");
int main(int argc, char* argv[])
{
bool verbose = true; // 用来决定是否开启日志组件
uint32_t nCsma = 3; // 定义csma网络中有多少个节点
CommandLine cmd;
cmd.AddValue("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue("verbose", "Tell echo applications to log if true", verbose);
cmd.Parse(argc, argv);
if (verbose) // 开启日志的情况下
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma = nCsma == 0 ? 1 : nCsma; //csma中最少一个节点
//创建p2p的两个节点
NodeContainer p2pNodes;
p2pNodes.Create(2);
//创建csma的网络节点
NodeContainer csmaNodes;
csmaNodes.Add(p2pNodes.Get(1)); // p2p的一号节点加入csma作为接入点
csmaNodes.Create(nCsma);
// 设置p2p的传输速率及延迟
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));
// p2p节点安装网卡
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install(p2pNodes);
// 设置csma的传输速率及延迟
// 注意传输速率有channel指定,而非device属性。(CSMA不允许同一信道上有多个不同数据率的设备)
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", StringValue("100Mbps"));
csma.SetChannelAttribute("Delay", TimeValue(NanoSeconds(6560)));
// csma节点安装网卡
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install(csmaNodes);
// 安装协议栈
InternetStackHelper stack;
stack.Install(p2pNodes.Get(0)); // p2p的0号节点安装
stack.Install(csmaNodes); //p2p的1号节点包含在csma中一起安装
Ipv4AddressHelper address;// 声明了一个地址助手对象
address.SetBase("10.1.1.0", "255.255.255.0");//从10.1.1.0 开始 以子网掩码为 255.255.255.0 分配地址
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign(p2pDevices);// 完成了p2p真正的地址配置
address.SetBase("10.1.2.0", "255.255.255.0");//从10.1.2.0 开始 以子网掩码为 255.255.255.0 分配地址
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign(csmaDevices);// 完成了csma真正的地址配置
// ***下面安装应用层
UdpEchoServerHelper echoServer(9);// 服务器端 port为9
// 将server服务器安装在CSMA的最后一个节点上即n4
ApplicationContainer serverApps = echoServer.Install(csmaNodes.Get(nCsma));
serverApps.Start(Seconds(1.0));// echoServer 在 1s 时开始
serverApps.Stop(Seconds(10.0));//echoServer 在 10s时结束
UdpEchoClientHelper echoClient(csmaInterfaces.GetAddress(nCsma), 9);//设定远程服务器的IP地址和Port
echoClient.SetAttribute("MaxPackets", UintegerValue(1));// 能发送的最大数据分组个数
echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0))); // 两个数据分组之间要等的时间
echoClient.SetAttribute("PacketSize", UintegerValue(1024)); // 每个数据分组的大小
// 将client服务器安装在p2p的第一个节点上即n0
ApplicationContainer clientApps = echoClient.Install(p2pNodes.Get(0));
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0));
// 建立网络路由
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
//开启p2pHelper,csmaHelper类对象的pcap追踪
pointToPoint.EnablePcapAll("second"); //
csma.EnablePcap("second", csmaDevices.Get(1), true);
Simulator::Run(); // 启动模拟器
Simulator::Destroy();
return 0;
}
third.cc
网络拓扑如下:
// Default Network Topology
//
// Wifi 10.1.3.0
// AP
// * * * *
// | | | | 10.1.1.0
// n5 n6 n7 n0 -------------- n1 n2 n3 n4
// point-to-point | | | |
// ================
// LAN 10.1.2.0
源码分析:
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/ssid.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("ThirdScriptExample");
int main(int argc, char* argv[])
{
bool verbose = true; // 用来决定是否开启日志组件
uint32_t nCsma = 3; // 定义csma网络中有多少个节点
uint32_t nWifi = 3; // 定义WIFI网络中有多少个节点
bool tracing = false;
CommandLine cmd;
cmd.AddValue("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue("nWifi", "Number of wifi STA devices", nWifi);
cmd.AddValue("verbose", "Tell echo applications to log if true", verbose);
cmd.AddValue("tracing", "Enable pcap tracing", tracing);
cmd.Parse(argc, argv);
// The underlying restriction of 18 is due to the grid position
// allocator's configuration; the grid layout will exceed the
// bounding box if more than 18 nodes are provided.
if (nWifi > 18)
{
std::cout << "nWifi should be 18 or less; otherwise grid layout exceeds the bounding box" << std::endl;
return 1;
}
if (verbose)
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
//创建p2p链路2个节点
NodeContainer p2pNodes;
p2pNodes.Create(2);
// 设置p2p的传输速率及延迟
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));
// p2p节点安装网卡
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install(p2pNodes);
//创建csma的网络节点
NodeContainer csmaNodes;
csmaNodes.Add(p2pNodes.Get(1));// p2p的一号节点加入csma作为接入点
csmaNodes.Create(nCsma);
// 设置csma的传输速率及延迟
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", StringValue("100Mbps"));
csma.SetChannelAttribute("Delay", TimeValue(NanoSeconds(6560)));
// csma节点安装网卡
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install(csmaNodes);
//创建WIFI的网络节点
NodeContainer wifiStaNodes;
wifiStaNodes.Create(nWifi);
NodeContainer wifiApNode = p2pNodes.Get(0);//设置wifi的AP(无线接入点)为p2p的第一个节点
//配置PHY和Channel通道助手
YansWifiChannelHelper channel = YansWifiChannelHelper::Default();
YansWifiPhyHelper phy = YansWifiPhyHelper::Default();
phy.SetChannel(channel.Create());//Channel对象与PHY对象关联
//MAC层配置
WifiHelper wifi;
wifi.SetRemoteStationManager("ns3::AarfWifiManager");//使用AARF速率控制算法
WifiMacHelper mac;
Ssid ssid = Ssid("ns-3-ssid");
mac.SetType("ns3::StaWifiMac",
"Ssid", SsidValue(ssid),
"ActiveProbing", BooleanValue(false));
NetDeviceContainer staDevices;//STA 网络设备
staDevices = wifi.Install(phy, mac, wifiStaNodes);//wifi的STA安装PHY层和MAC层
//配置wifi网络AP网络设备的MAC类型和基础设施网络的SSID
mac.SetType("ns3::ApWifiMac",
"Ssid", SsidValue(ssid));
NetDeviceContainer apDevices;
apDevices = wifi.Install(phy, mac, wifiApNode);//与STA共同的PHY特性
MobilityHelper mobility;//移动模型
//网格位置分配器
mobility.SetPositionAllocator("ns3::GridPositionAllocator",
"MinX", DoubleValue(0.0),
"MinY", DoubleValue(0.0),
"DeltaX", DoubleValue(5.0),
"DeltaY", DoubleValue(10.0),
"GridWidth", UintegerValue(3),
"LayoutType", StringValue("RowFirst"));
mobility.SetMobilityModel("ns3::RandomWalk2dMobilityModel",//以随机游走的方式移动
"Bounds", RectangleValue(Rectangle(-50, 50, -50, 50)));
mobility.Install(wifiStaNodes);//安装到wifi网络的STA
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
mobility.Install(wifiApNode);//安装到wifi网络的AP
//安装协议栈
InternetStackHelper stack;
stack.Install(csmaNodes);
stack.Install(wifiApNode);
stack.Install(wifiStaNodes);
Ipv4AddressHelper address;
address.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign(p2pDevices);
address.SetBase("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign(csmaDevices);
address.SetBase("10.1.3.0", "255.255.255.0");
address.Assign(staDevices);
address.Assign(apDevices);
//安装应用
UdpEchoServerHelper echoServer(9);
ApplicationContainer serverApps = echoServer.Install(csmaNodes.Get(nCsma));
serverApps.Start(Seconds(1.0));
serverApps.Stop(Seconds(10.0));
UdpEchoClientHelper echoClient(csmaInterfaces.GetAddress(nCsma), 9);
echoClient.SetAttribute("MaxPackets", UintegerValue(1));
echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0)));
echoClient.SetAttribute("PacketSize", UintegerValue(1024));
ApplicationContainer clientApps =
echoClient.Install(wifiStaNodes.Get(nWifi - 1));//在随后建立的wifi STA上安装客户机
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0));
//建立网络路由
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
Simulator::Stop(Seconds(10.0));//无线接入点会一直产生信标,模拟器时间列表一直非空,仿真无法结束
if (tracing == true)
{
pointToPoint.EnablePcapAll("third");
phy.EnablePcap("third", apDevices.Get(0));
csma.EnablePcap("third", csmaDevices.Get(0), true);
}
Simulator::Run();
Simulator::Destroy();
return 0;
}
总结:
通过分析以上三个源码,不难发现:
拓展
仿照上述程序,编写一个由两个LAN互联形成的网络。
myfourth.cc
网络拓扑如下:
// Default Network Topology
//
//
// n3 n2 n1 n0 -------------- n4 n5 n6 n7
// | | | | point-to-point | | | |
// ================ ================
// LAN 10.1.1.0 LAN 10.1.2.0
源码分析:
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/netanim-module.h"
using namespace ns3;
// 定义一个日志组件
NS_LOG_COMPONENT_DEFINE("MyfourthScriptExample");
int main(int argc, char* argv[])
{
bool verbose = true; // 用来决定是否开启日志组件
uint32_t nCsma_1 = 3; // 定义csma1网络中有多少个节点
uint32_t nCsma_2 = 3; // 定义csma2网络中有多少个节点
CommandLine cmd;
cmd.AddValue("nCsma_1", "Number of \"extra\" CSMA nodes/devices", nCsma_1);
cmd.AddValue("nCsma_2", "Number of \"extra\" CSMA nodes/devices", nCsma_2);
cmd.AddValue("verbose", "Tell echo applications to log if true", verbose);
cmd.Parse(argc, argv);
if (verbose) // 开启日志的情况下
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma_1 = nCsma_1 == 0 ? 1 : nCsma_1; //csma中最少一个节点
nCsma_2 = nCsma_2 == 0 ? 1 : nCsma_2;
//创建p2p的两个节点
NodeContainer p2pNodes;
p2pNodes.Create(2);
//创建csma_1的网络节点
NodeContainer csmaNodes_1;
csmaNodes_1.Add(p2pNodes.Get(0)); // p2p的0号节点加入csma1作为接入点
csmaNodes_1.Create(nCsma_1);
//创建csma_2的网络节点
NodeContainer csmaNodes_2;
csmaNodes_2.Add(p2pNodes.Get(1)); // p2p的1号节点加入csma2作为接入点
csmaNodes_2.Create(nCsma_2);
// 设置p2p的传输速率及延迟
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
pointToPoint.SetChannelAttribute("Delay", StringValue("2ms"));
// p2p节点安装网卡
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install(p2pNodes);
// 设置csma的传输速率及延迟
// 注意传输速率有channel指定,而非device属性。(CSMA不允许同一信道上有多个不同数据率的设备)
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", StringValue("100Mbps"));
csma.SetChannelAttribute("Delay", TimeValue(NanoSeconds(6560)));
// csma节点安装网卡
NetDeviceContainer csmaDevices_1;
csmaDevices_1 = csma.Install(csmaNodes_1);
NetDeviceContainer csmaDevices_2;
csmaDevices_2 = csma.Install(csmaNodes_2);
// 安装协议栈
InternetStackHelper stack;
//stack.Install(p2pNodes); // p2p不需要独立安装
stack.Install(csmaNodes_1); //p2p的0号节点包含在csma1中一起安装
stack.Install(csmaNodes_2); //p2p的1号节点包含在csma2中一起安装
// 下面是ip的分配
Ipv4AddressHelper address;// 声明了一个地址助手对象
address.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign(p2pDevices);
address.SetBase("10.1.3.0", "255.255.255.0");//从10.1.1.0 开始 以子网掩码为 255.255.255.0 分配地址
Ipv4InterfaceContainer csmaInterfaces_1;
csmaInterfaces_1 = address.Assign(csmaDevices_1);// 完成了csma1真正的地址配置
address.SetBase("10.1.2.0", "255.255.255.0");//从10.1.2.0 开始 以子网掩码为 255.255.255.0 分配地址
Ipv4InterfaceContainer csmaInterfaces_2;
csmaInterfaces_2 = address.Assign(csmaDevices_2);// 完成了csma2真正的地址配置
// ***下面安装应用层
UdpEchoServerHelper echoServer(9);// 服务器端 port为9
// 将server服务器安装在CSMA2的最后一个节点上即n7
ApplicationContainer serverApps = echoServer.Install(csmaNodes_2.Get(nCsma_2));
serverApps.Start(Seconds(1.0));// echoServer 在 1s 时开始
serverApps.Stop(Seconds(10.0));//echoServer 在 10s时结束
UdpEchoClientHelper echoClient(csmaInterfaces_2.GetAddress(nCsma_2), 9);//设定远程服务器的IP地址和Port
echoClient.SetAttribute("MaxPackets", UintegerValue(1));// 能发送的最大数据分组个数
echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0))); // 两个数据分组之间要等的时间
echoClient.SetAttribute("PacketSize", UintegerValue(1024)); // 每个数据分组的大小
// 将client服务器安装在csma1的最后一个节点上即n3
ApplicationContainer clientApps = echoClient.Install(csmaNodes_1.Get(nCsma_1));
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0));
// 建立网络路由
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
//开启p2pHelper,csmaHelper类对象的pcap追踪
pointToPoint.EnablePcapAll("Myfourth"); //
csma.EnablePcap("Myfourth", csmaDevices_1.Get(nCsma_1), true);
csma.EnablePcap("Myfourth", csmaDevices_2.Get(nCsma_2), true);
AnimationInterface anim("myfourth.xml");
anim.SetConstantPosition(csmaNodes_1.Get(0), 5.0, 4.0);
anim.SetConstantPosition(csmaNodes_1.Get(1), 3.0, 2.0);
anim.SetConstantPosition(csmaNodes_1.Get(2), 5.0, 2.0);
anim.SetConstantPosition(csmaNodes_1.Get(3), 7.0, 2.0);
anim.SetConstantPosition(csmaNodes_2.Get(0), 5.0, 6.0);
anim.SetConstantPosition(csmaNodes_2.Get(1), 3.0, 8.0);
anim.SetConstantPosition(csmaNodes_2.Get(2), 5.0, 8.0);
anim.SetConstantPosition(csmaNodes_2.Get(3), 7.0, 8.0);
Simulator::Run(); // 启动模拟器
Simulator::Destroy();
return 0;
}
注意:
p2p的两个节点分别是两个CSMA的接入点,编程时:
- 安装网卡时要分别独立安装
- 协议栈p2p不需要重复安装
- IP分配需要重复分配
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本