NS-3 MyFirstScriptExample
安装好了NS-3之后,我根据一些教程学习了NS-3的几个关键的概念,然后照着例子和自己对它的一些理解,尝试的打了我自己的第一个脚本程序:MyFirstScriptExample 具体代码如下:
#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"
using namespace std;
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("MyFirstScriptExample");
int main()
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
NodeContainer nodes;
nodes.Create(2);
PointToPointHelper ptpHelper;
ptpHelper.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
ptpHelper.SetChannelAttribute("Delay", StringValue("2ms"));
NetDeviceContainer devices;
devices = ptpHelper.Install(nodes);
InternetStackHelper stackHelper;
stackHelper.Install(nodes);
Ipv4AddressHelper addressHelper;
addressHelper.SetBase("10.1.1.0", "255.255.255");
Ipv4InterfaceContainer interfaces;
interfaces = addressHelper.Assign(devices);
UdpEchoServerHelper echoServerHelper(9);
ApplicationContainer serverApps;
serverApps = echoServerHelper.Install(nodes.Get(1));
serverApps.Start(Seconds(1.0));
serverApps.Stop(Seconds(10.0));
UdpEchoClientHelper echoClientHelper(interfaces.GetAddress(1), 9);
echoClientHelper.SetAttribute("MaxPackets", UintegerValue(1));
echoClientHelper.SetAttribute("Interval", TimeValue(Seconds(1.0)));
echoClientHelper.SetAttribute("PacketSize", UintegerValue(1024));
ApplicationContainer clientApps;
clientApps = echoClientHelper.Install(nodes.Get(0));
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
程序分析:
第一部分
一.头文件部分
#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"
NS-3根据不同的模块具有的功能,将头文件分类,按照我的理解,上面的几个模块头文件在程序编译的时候回递归的加载该模块中会使用到的所有头文件,也就是说它是一组头文件。这样做的好处:省去了寻找头文件所浪费的不必要时间。
可以在.../.../build/debug/ns3目录找到上文的四个头文件,查看该内容就可以知道它们包括了该模块所有相关的头文件。
二.using namespace ns3
NS-3工程是在名为ns3的命名空间里面实现的,可以参考C++的命名空间std。
三.日志组件
NS_LOG_COMPONENT_DEFINE ("MyFirstScriptExample");
引用:“这一行声明了一个叫MyFirstScriptExample的日志组件,通过引用MyFirstScriptExample这个名字的操作,可以实现打开或者关闭控制台日志的输出。”
这里的话我暂时也只了解到一些皮毛,等到学习到相关内容再进行记录。
包括主函数的这两句:
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
引用:“用来使两个日志组件生效的。它们被内建在Echo Client 和Echo Server 应用中”
四.NodeContainer
NodeContainer nodes;
nodes.Create(2);
第一行声明了类 NodeContainer 的一个对象 nodes,第二行调用 NodeContainer 的方法 Creat() 创建了两个节点。
五.PointToPointHelper
关于拓扑辅助工具Helper:按照我的理解,是我们构建拓扑结构 和 配置连接NetDevices和Channel的得力助手,MyFirstScriptExample多次利用Helper的帮助(Install等方法)来对类的对象进行赋值(或者说,配置这些对象的某些属性)。
PointToPointHelper ptpHelper; //定义一个 PointToPointHelper 类的对象 ptpHelper
ptpHelper.SetDeviceAttribute("DataRate", StringValue("5Mbps")); //设置Device(网络设备)的 DataRate(数据速率) 属性为5Mbps
ptpHelper.SetChannelAttribute("Delay", StringValue("2ms")); //设置Channel(信道)的 Delay(延迟) 属性为2ms
通过ptpHelper的 SetDeviceAttribute 和 SetChannelAttribute 方法,设置了网络设备和信道的相关属性,这样做的好处是,当使用ptpHelper的Install方法 建立 NetDeviceContainer 的对象 devices 的时候,对网络设备和信道相关属性的设置与之前 ptpHelper 的设置一致。
六.NetDeviceContainer
我们现在有“一个准备在两个节点之间创建PointToPointNetDevices和wirePointToPointChannel对象的PointToPointHelper对象” ptpHelper, ptpHelper 的作用在这个时候就体现出来了,引用:“正如我们使用NodeContainer对象来为我们创建节点,我们会让ptpHelper来做关于创建,配置和安装设备的工作。”
NetDeviceContainer devices;
devices = ptpHelper.Install(nodes); //有一个PointToPointChannel对象被创建,两个PointToPointNetDevices与之连接
经过这两句的处理之后,我们有两个节点,每一个节点安装有点到点的网络设备,一共两个节点,在它们之间有一个点到点的信道。
两个设备会被配置在一个有2ms传输延时的信道上以5Mbps的速率传输数据。
七.InternetStackHelper
InternetStackHelper stackHelper;
stackHelper.Install(nodes); //为节点容器中的每一个节点安装协议栈(TCP,IP等)
InternetStackHelper 是一个辅助安装网络协议栈的helper类,经过其方法Install (实参为 NodeContainer 的对象,节点容器)的处理之后,每一个节点都安装了协议栈。
八.Ipv4AddressHelper 和 Ipv4InterfaceContainer 进行IP地址的分配
利用 Ipv4AddressHelper 类来对每一个节点的网络设备分配IP地址。与之前 PointToPointHelper 的作用相似。
Ipv4AddressHelper addressHelper;
addressHelper.SetBase("10.1.1.0", "255.255.255"); //设置属性:从10.1.1.0开始以子网掩码为255.255.255.0分配地址
Ipv4InterfaceContainer interfaces;
interfaces = addressHelper.Assign(devices); //完成了真正的地址配置
利用 Ipv4InterfaceContainer 的对象 interfaces 将一个IP地址同一个网络设备相关联起来。
在第一部分结束之后,我们有了一个安装了协议栈,配置了IP地址的点到点的网络。剩下的所要做的事情是运用它来产生数据通信。
第二部分
**一.Application 类 **
**(1)echo服务端 UdpEchoServerApplication **
目的:在我们之前创建的节点上设置一个 UDP 回显服务应用。
UdpEchoServerHelper echoServerHelper(9);
ApplicationContainer serverApps;
serverApps = echoServerHelper.Install(nodes.Get(1)); //Install()这个方法的执行,才初始化回显服务器的应用,并将应用连接到一个节点上去。
serverApps.Start(Seconds(1.0)); //使echo服务应用在1s时开始(生效)
serverApps.Stop(Seconds(10.0)); //在10s时停止(失效)
同样的,利用了 UdpEchoSeverHelper 辅助工具的作用。这里原文的作者有两段话写的很清楚,贴出来:
同其它helper对象类似,UdpEchoServerHelper对象有一个Install()方法。实际上是这个方法的执行,才初始化回显服务器的应用,并将应用连接到一个节点上去。
···
我们现在会看到echoServerHelper.Install将会在管理节点的NodeContainer容器索引号为1的机节点上安装一个UdpEchoServerApplication。安装会返回一个容器,这个容器中包含了指向所有被helper对象创建的应用指针。
也就是说,经过了上面的几行代码的一系列操作,我们在一个节点(NodeContainer容器索引号为1)上面安装了Echo服务端应用,并且我们声明的这个模拟事情,会持续10s。
(2)echo客户端 UdpEchoClientApplication
echo客户端应用的设置与回显服务器端类似。
UdpEchoClientHelper echoClientHelper(interfaces.GetAddress(1), 9);
//UdpEchoClientHelper构造函数的格式,我们传递了”RemoteAdress”和”RemotePort”属性,来实例化对象。
//设置客户端的远端地址为服务器节点的IP地址。我们同样告诉它准备发送数据包到端口9。
echoClientHelper.SetAttribute("MaxPackets", UintegerValue(1)); //MaxPackets: 允许它在模拟期间所能发送的最大数据包个数
echoClientHelper.SetAttribute("Interval", TimeValue(Seconds(1.0))); //Interval: 在两个数据包之间要等待多长时间
echoClientHelper.SetAttribute("PacketSize", UintegerValue(1024)); //PacketSize: 它的数据包应该承载多少数据,数据包的大小
ApplicationContainer clientApps;
clientApps = echoClientHelper.Install(nodes.Get(0));
clientApps.Start(Seconds(2.0));
clientApps.Stop(Seconds(10.0)); //客户端在模拟器中时间为2s的时候开始(即服务端生效1s后才开始)。
二.Simulator类 运行模拟器
Simulator::Run(); //开始模拟
Simulator::Destroy(); //结束,同时进行清理工作