NS3 网络模拟器基础

文章目录

NS3初探

一、简介

NS3是一款离散事件驱动的网络仿真器,主要应用于研究和教育领域,旨在满足学术和教学的需求。NS3项目是一个完全开源的开发工程,于2006年启动。第一个版本发布于2008年6月,目前最新的版本为ns-3.35。NS3适用于Linux和Mac OS操作系统。

NS3和NS2

NS-3并不是NS-2的扩展,而是一个全新的模拟器。 NS-2采用C++和OTcl代码编写,在学习过程中需要学习新的OTcl语言。而NS-3全部采用C++语言编写,并且带有可选择性的Python语言绑定,用户可以选择C++或者Python语言编写脚本代码,使用起来更加灵活。

NS-3并不支持NS-2的API。虽然NS-2中的一些模块已经移植到了NS-3中,但NS-3远没有NS-2完善。在NS-3开发的过程中,NS-3项目组会继续维护NS-2,同时也会研究过渡和整合机制。NS-3并不包含目前所有NS-2的功能,但它具有某些新的特性,如:正确的多网卡处理、IP寻址策略的使用、更详细的802.11模块等等。

二、NS3重要概念

NS架构

1 节点——Node类

在网络术语中,任何一台连接到网络的计算设备被称为主机,亦称为终端。NS3是一个网络模拟器,而非一个专门的因特网模拟器,为此我们避开术语“主机”,因为这个词太容易让人联想到因特网和及其相关协议。因此,我们选用了一个来源于图论,在其他网络模拟器亦广泛使用的术语:节点。

NS3中基本计算设备被抽象为节点。节点由用C++编写的Node类来描述。Node类提供了用于管理计算设备的各种方法。

可以将节点设想为一台可以添加各种功能的计算机。为了使一台计算机有效地工作,我们可以给它添加应用程序,协议栈,外设卡及驱动程序等。NS3采用了与此相同的模型。

2 信道——Channel类

在现实世界中,人们可以把计算机连接到网络上。通常我们把网络中数据流流过的媒介称为信道。当把以太网线插入到墙壁上的插孔时,你正通过信道将计算机与以太网连接。

在NS3中,可以把节点连接到代表数据交换信道的对象上。在这里,基本的通信子网这一抽象概念被称为信道,用C++编写的Channel类来描述。

Channel类提供了管理通信子网对象和把节点连接至信道的各种方法。信道类同样可以由开发者以面向对象的方法自定义。一个信道实例可以模拟一条简单的线缆(wire),也可以模拟一个复杂的巨型以太网交换机,甚至无线网络中充满障碍物的三维空间。

有几个重要的信道模型的实例,包括:

  • CsmaChannel(CsmaChannel信道模拟了用于一个可以实现载波侦听多路访问的信道,这个信道具有和以太网相似的功能。)
  • PointToPointChannel(P2P信道,即点对点信道)
  • WifiChannel(Wifi信道)。

3 网络设备——NetDevice类

如果想把一台计算机连接到网络上,必须在计算机上安装有网卡。一张网卡如果缺少控制硬件的软件驱动是不能工作的。在Unix/Linux系统中,外围硬件被划为“设备”。设备通过驱动程序来控制,而网卡通过网卡驱动程序来控制。在Unix/Linux系统中,网卡被称为像eth0这样的名字。

在NS3中,网络设备这一抽象概念相当于硬件设备和软件驱动的总和。NS3仿真环境中,网络设备相当于安装在节点上,使得节点通过信道和其他节点通信。像真实的计算机一样,一个节点可以通过多个网络设备同时连接到多条信道上

网络设备由用C++编写的NetDevice类来描述。NetDevice类提供了管理连接其他节点和信道对象的各种方法,并且允许开发者以面向对象的方法来自定义。

有几个特定的网络设备的实例,它们分别是CsmaNetDevice,PointToPointNetDevice, 和WifiNetDevice

正如以太网卡被设计成在以太网中工作一样,CsmaNetDevice被设计成在csma信道中工作,而PointToPointNetDevice在PointToPoint信道中工作,WifiNetNevice在wifi信道中工作。

4 应用程序——Application类

计算机软件通常可分为两大类:系统软件和应用软件。系统软件根据计算模型配置,并管理计算机中的各种资源,如内存,处理器周期,硬盘,网络等。系统软件通常并不直接使用这些资源来完成用户任务。用户往往需要运行应用程序来完成一些特定的任务,而应用程序需要使用由系统软件控制的资源。

通常,系统软件和应用软件的界线表现为特权级别的变化,而这种变化是通过操作系统的自陷功能(operating systemtraps)来实现的。在NS3中并没有真正的操作系统的概念,更没有特权级别或者系统调用的概念。然而,我们有应用程序的概念。正如“现实世界”中在计算机上运行应用程序以执行各种任务一样,NS3仿真环境中的应用程序在节点上运行来驱动模拟过程。

在NS3中,需要被仿真的用户程序被抽象为应用。用Application类来描述。这个类提供了管理仿真过程中用户层应用的各种方法。开发者应当用面向对象的方法自定义和创建新的应用。

经常使用有Application类的两个实例:UdpEchoClientApplication和UdpEchoServerApplication。这些应用程序包含了一个client应用和一个server应用来发送和回应仿真网络中的数据包。

5 拓扑帮助-topology helper

实际网络中有具有添加(或内置)NIC的主机。 在NS3中,则称为有带有NetDevices的节点。 在大型模拟网络中,您需要在节点,NetDevices和Channels之间安排许多连接。

由于将NetDevices连接到节点,NetDevices到通道,分配IP地址等是ns-3中的常见任务,因此我们提供了拓扑辅助工具,以使其尽可能简单。

例如,可能需要许多不同的ns-3核心操作来创建NetDevice,添加MAC地址,在节点上安装该网络设备,配置节点的协议栈,然后将NetDevice连接到Channel。 将多个设备连接到多点通道然后将各个网络连接到互联网络中将需要更多操作。 我们提供拓扑辅助对象,将这些许多不同的操作组合成一个易于使用的模型,以方便您使用。

6 节点容器–NodeContainer

一个节点Node代表了一台计算机,我们将添加协议栈,应用程序和外围卡等内容。 NodeContainer拓扑助手提供了一种方便的方法来创建,管理和访问我们创建的任何Node对象,以便运行模拟。

7 设备容器–NetDeviceContainer

正如使用NodeContainer拓扑辅助对象为模拟创建节点一样,我们将要求PointToPointHelper完成创建,配置和安装设备所涉及的工作。 我们需要有一个创建的所有NetDevice对象的列表,所以使用NetDeviceContainer来保存它们就像使用NodeContainer来保存创建的节点一样。

三、分析例子程序first.cc的源代码

1.文件开头定义

 1#include "ns3/core-module.h"   //内核模块
 2#include "ns3/network-module.h"
 3#include "ns3/internet-module.h"
 4#include "ns3/point-to-point-module.h"   //p2p模块
 5#include "ns3/applications-module.h"   //应用程序
 6
 7using namespace ns3;   
 8/*命名空间,NS3工程是在一个叫做ns3的C++命名空间中实现的。这把所有与ns3相关的声明,集中在一个与全局命名空间相区别的命名空间中。
 9我们希望这样会给ns3与其他代码的集成带来好处。C++用“using”语句用来把ns-3namespace引入到当前的(全局的)作用域中。
10这个声明就是说,你不用为了使用ns-3的代码而必须在所有的ns-3代码前打上ns3::作用域操作符。*/
11
12NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");   
13/*声明一个叫"FirstScriptExample"的日志组件,通过引用FirstScriptExample这个名字的操作,
14可以实现打开或者关闭控制台日志的输出。*/

2.进入主函数

1int
2main (int argc, char *argv[])  //主函数
3{ 
4//日志输出设定
5  Time::SetResolution (Time::NS);  //时间分辨率设定为纳秒(系统默认)
6  /*服务端输出和客户端输出的级别为INFO,是设置在日志里显示的信息种类的,
7  这个脚本是被内建在UdpEchoClientApplication和UdpEchoServerApplication两个应用中的*/
8  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
9  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

①创建节点

1//用NodeContainer类,创建两个节点
2  NodeContainer nodes;
3  nodes.Create (2);

②创建链路类型

1//构建p2p信道模型(就是点对点)
2
3  /*用到了拓扑辅助工具的helper类,在这个脚本中使用了PointToPointHelper
4  来配置和连接网络设备PointToPointNetDevice和信道PointToPointChannel对象*/
5  PointToPointHelper pointToPoint;   //产生一个对象pointToPoint
6  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));   //用这个对象设置设备属性——数据速率为5Mbps
7  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));    //用这个对象设置信道属性——时延为2ns

③创建网络设备并安装

 1//用NetDeviceContainer类,创建网络设备
 2
 3  NetDeviceContainer devices;   
 4  devices = pointToPoint.Install (nodes);  
 5  /*在Install()方法内,以一个NodeContainer对象作为一个参数(nodes),一个NetDeviceContainer
 6  被创建了。对于在NodeContainer对象中的每一个节点(对于一个点到点链路必须明确有两个节点),都将
 7      ①有一个PointToPointNetDevice被创建和保存在设备容器内;
 8      ②有一个PointToPointChannel对象被创建,两个PointToPointNetDevices与之连接。
 9  并且,当PointToPointHelper对象创建时,那些在helper中被预先设置的属性被用来初始化对象对应的属性值。
10  因为nodes是两个节点,所以这条语句的作用是:
11      ①用两个nodes生成两个NodeContainer对象,保存在设备容器devices内;
12      ②用两个nodes创建一个PointToPointChannel对象;
13      ③上面的两个PointToPointNetDevices与PointToPointChannel连接;
14	  ④把生成的devices安装到nodes结点上。*/

④安装协议栈

1//我们现在已经配置了节点和设备,但是我们还没有在节点上安装任何协议栈。下面两行代码完成这个任务
2
3  /*类InternetStackHelper是一个辅助安装网络协议栈的helper类,和pointToPointHelper类
4  一样,首先产生类的对象stack,然后用这个类的install(),install的对象同样是NodeContainer对象,
5  它会为节点容器中的每一个节点安装一个网络协议栈(TCP,UDP,IP等)*/
6  InternetStackHelper stack;
7  stack.Install (nodes);

⑤设置IP地址

1//下面我们需要为节点上的设备设置IP地址。
2
3  /*Ipv4AddressHelper类是用来管理IP地址的分配的。当执行实际的地址分配时唯一用户可见的API
4  是设置IP地址和子网掩码,网络层采用ipv4分配ip,并且告诉它应该开始从10.1.1.0开始以子网掩码
5  为255.255.255.0分配地址。地址分配默认是从1开始并单调的增长,所以在这个基础上第一个分配的
6  地址会是10.1.1.1,紧跟着是10.1.1.2等等。底层NS3系统事实上会记住所有分配的IP地址,如果你
7  无意导致了相同IP地址的产生,这将是一个致命的错误。*/
8  Ipv4AddressHelper address;
9  address.SetBase ("10.1.1.0", "255.255.255.0"); 

⑥配置网络接口

1  Ipv4InterfaceContainer interfaces = address.Assign (devices);  
2  /*最后这行代码实现给devices分配地址,将一个IP地址同一个网络设备关联起来。正如我们有时候需
3  要一个网络设备列表一样,我们有时候需要一个Ipv4Interface对象的列表。Ipv4InterfaceContainer
4  提供了这样的功能。*/

⑦安装应用

 1//现在我们有了一个安装了协议栈,配置了IP地址的点到点的网络。剩下的所要做的事情是运用它来产生数据通信
 2
 3  /*NS3系统的另一个核心抽象是Application类。在这个脚本中我们用两个特定的Application类:
 4UdpEchoServerApplication(UDP 回显服务应用)和UdpEchoClientApplication(UDP 回显客
 5户应用)。正如我们先前声明过的一样,我们使用helper对象来帮助配置和管理潜在的对象。在这里,
 6我们用UdpEchoServerHelper和UdpEchoClientHelper对象来使我们的工作更加容易点。
 7  首先用Helper类创建一个应用echoServer,像往常一样,这个并非应用本身,这是一个用来帮助创
 8  建真正应用的helper对象。我们约定在helper类的对象中放置必需的属性。本例中,我们告知helper
 9  对象服务器和客户端所共知的一个端口号9,否则这个helper对象是不会起任何作用的。*/
10  UdpEchoServerHelper echoServer (9); 
11  
12  /*echoServer.Install将会在管理节点的NodeContainer容器nodes索引号为1的机节点上安装一个
13  UdpEchoServerApplication。安装会返回一个容器,这个容器中包含了指向所有被helper对象创建
14  的应用指针。*/
15  ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
16  
17  /*应用程序对象需要一个时间参数来“开始”产生数据通信并且可能在一个可选的时间点“停止”。我们
18  提供了开始和停止的两个参数。这些时间点是用ApplicationContainer的方法Start和Stop来设置的。
19  这些方法以”Time”对象为参数。本例中,我们传递了double类型对象1.0到Seconds的一个方法,通过
20  seconds()方法,把它转换到ns-3的Time对象。*/
21  serverApps.Start (Seconds (1.0));  //起始时间(仿真)
22  serverApps.Stop (Seconds (10.0));  //停止时间
23
24//与上面类似,生成UdpEchoClientApplication(UDP 回显客户应用)
25
26  /*设置这个客户helper类对象的属性,告诉它设置客户端的远端地址为服务器节点的IP地址
27  interfaces.GetAddress (1)。我们同样告诉它准备发送数据包到端口9。*/
28  UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);  
29//设置发包属性
30  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));  
31  //“MaxPackets”属性告诉客户端我们所允许它在模拟期间所能发送的最大数据包个数
32  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));  
33  //“Interval”属性告诉客户端在两个数据包之间要等待多长时间。
34  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));  
35  //“PacketSize”属性告诉客户端它的数据包应该承载多少数据。本例中,我们让客户端发送一个1024字节的数据包。
36 
37  /*同理,echoClient.Install将会在管理节点的NodeContainer容器nodes索引号为0的机节点上安装一个
38  UdpEchoClientApplication。安装会返回一个容器,这个容器中包含了指向所有被helper对象创建的应用指针。*/
39  ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));   //将Node0作为客户机

⑧开始仿真

 1  clientApps.Start (Seconds (2.0));  //起始、停止时间
 2  clientApps.Stop (Seconds (10.0));
 3
 4 
 5   /*下面我们所需要做的就是运行模拟器,这是用全局函数Simulator::Run.来做到的。
 6  当Simulator::Run被调用时,系统会开始遍历预设事件的列表并执行。首先它会在1.0s时
 7  运行事件,这个事件会使echo服务端应用生效(这个事件会预设更多的其他事件)。接下来
 8  仿真器会运行在t=2.0s时的事件,即让echo客户端应用开始。同样的,这个事件可能会预定
 9  更多的其他事件。在echo客户端应用中的开始事件的执行会通过给服务端传送一个数据包来
10  开始仿真的数据传送阶段。*/
11  Simulator::Run ();    //运行仿真
12
13   /*下面剩下的事情就是清理了。这个通过调用全局函数Simulator::Destroy来完成。
14  当该方法被执行后,模拟器中所有创建的对象将被销毁。你自己并不需要追踪任何对象,
15  你所需要做的仅仅是调用Simulator::Destroy并且退出。ns-3系统会帮你料理这些繁
16  杂的任务。*/
17  Simulator::Destroy ();   //结束仿真
18  return 0;
19}

四、NS3配套工具

1.waf编译器

下载NS3的源码之后,需要对源码进行编译来生成可执行程序。正如源码管理方式多种多样,编译源码也有多种工具。最常用的工具是make。Make的不足在于,它可能是编译大型和高可配置型系统最难的一种方法。因此,有很多替代工具被开发出来。最近,大型高可配置系统的编译工具大多选择用Python语言来开发。

NS3的编译系统采用了Waf,它是用Python开发的新一代编译管理系统。读者不必掌握python,即可编译现有的NS3项目。如果读者想要扩展现有的NS3系统,大多数情况只需了解Python知识的很少且非常直观的一个子集。

使用方法

1./waf     //编译
2./waf --run myfirst   //运行文件

2.vim/gedit

vi、vim、gedit都是一样的,用以打开文本编辑器

1vim scratch/myfirst.cc   
2gedit scratch/myfirst.cc   //用文本编辑器打开文件

3.gnuplot

gnuplot是一个命令行驱动的交互式绘图工具(command-driven interactive function plotting program),可将数学函数或数值资料以平面图或立体图的形式画在不同种类终端机或绘图输出装置上。它是由Colin Kelley 和 Thomas Williams于1986年开发的绘图程序发展而来的,可以在多个平台下使用。gnuplot既支持命令行交互模式,也支持脚本。

使用方法:

①直接进行交互,用下列命令,进入交互界面,然后可以用语句控制画图

1gnuplot

控制画图:

 1set termianl png //设置输出图片格式,如png,gif,jpg等 
 2set size width,height //设备图片宽度,高度 
 3set output “图片名称” //设置保存图片名称。
 4plot title “标题名” //设置图片标题名称,一般用英文,有时不支持中文字符 
 5plot “数据.dat” using 1:2 with linespoints //把数据文件”数据.dat”输出图像, using 1:2,使用第1,2列数据输出. 
 6with linespoints //点用符号,点与点之间用线连接
 7a plot “数据.dat” //只输出数据点 
 8b plot “数据.dat” with lines //把点连起来,成线。 
 9c plot “数据.dat” with linespoints //点用符号,点与点之间用线连接 
10d plot ‘file.dat’ using 1:3 with linespoints //使用1,3列绘图 
11e plot ‘file.dat’ using 1:($3/2) with linespoints //使用第一列与第三列的二分之一绘图

②使用gnuplot类在文件中编写,生成文件xxx.plt,然后用gnuplot打开该文件 重要指令:

 1GnuplotCollection gnuplots ("main-propagation-loss.pdf");
 2  //GnuplotCollection可以将多个图放在一个文件中,和Gnuplot没有什么区别
 3  
 4  {//第一个图
 5    Ptr<FriisPropagationLossModel> friis = CreateObject<FriisPropagationLossModel> ();
 6    Gnuplot plot = TestDeterministic (friis); //生成一个plot对象
 7    plot.SetTitle ("xxx"); //设置plot标题
 8    gnuplots.AddPlot (plot);//往gnuplots 图集合中增加一个图
 9  }
10 //定义文件:
11  std::ofstream plotFile(propagation_loss.plt);
12  //用这个声明的流对象作为GenerateOutput的参数,就是把上面GnuplotCollection类的gnuplots输出放进文件里
13  gnuplots.GenerateOutput(plotFile);
14  // produce clean valgrind
15  Simulator::Destroy ();
16  return 0;
17}

在程序执行完之后,该文件会出现在ns-3.xx文件夹下。进入该文件夹下,执行下列命令即可生成main-propagation-loss.pdf文件。

1gnuplot propagation_loss.plt

例如文件为:

 1#include <fstream>   //使得程序能够将仿真结果输出到文件中以便后续绘图和分析。
 2
 3int main (int argc, char *argv[])
 4{
 5  CommandLine cmd;
 6  cmd.Parse (argc, argv);
 7  
 8  GnuplotCollection gnuplots ("main-propagation-loss.pdf");
 9  //GNUplot是一个将数据图形化的库,GnuplotCollection可以将多个图放在一个文件中
10  
11  {//第一个图
12    Ptr<FriisPropagationLossModel> friis = CreateObject<FriisPropagationLossModel> ();
13	//testDeterministic方法是计算相应信道模型功率和距离的对应关系
14    Gnuplot plot = TestDeterministic (friis); //生成一个plot对象
15    plot.SetTitle ("ns3::FriisPropagationLossModel (Default Parameters)"); //设置plot标题
16    gnuplots.AddPlot (plot);//往gnuplots 图集合中增加一个图
17  }
18
19  {//第二个图
20    Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
21    log->SetAttribute ("Exponent", DoubleValue (2.5));
22    Gnuplot plot = TestDeterministic (log);
23    plot.SetTitle ("ns3::LogDistancePropagationLossModel (Exponent = 2.5)");
24    gnuplots.AddPlot (plot);
25  }
26
27  {//第三个图
28    Ptr<RandomPropagationLossModel> random = CreateObject<RandomPropagationLossModel> ();
29    Ptr<ExponentialRandomVariable> expVar = CreateObjectWithAttributes<ExponentialRandomVariable> ("Mean", DoubleValue (50.0));
30    random->SetAttribute ("Variable", PointerValue (expVar));
31
32    Gnuplot plot = TestDeterministic (random);
33    plot.SetTitle ("ns3::RandomPropagationLossModel with Exponential Distribution");
34    gnuplots.AddPlot (plot);
35  }
36  ...一共九个图
37
38  //定义文件:
39  std::ofstream plotFile(propagation_loss.plt);
40  //用这个声明的流对象作为GenerateOutput的参数,就是把上面GnuplotCollection类的gnuplots输出放进文件里
41  gnuplots.GenerateOutput(plotFile);
42  // produce clean valgrind
43  Simulator::Destroy ();
44  return 0;
45}

在程序执行完之后,该文件会出现在ns-3.xx文件夹下。进入该文件夹下,执行下列命令:

1gnuplot propagation_loss.plt

在该文件夹下生成一个名为main-propagation-loss.pdf的文件,打开该文件(pdf文件直接打开即可),可以看到上述代码所生成的路径损耗模型图形。 如下图:

4.netanim

NetAnim是一个独立的、基于Qt4的离线动画演示工具,在NS 3方针过程中生成XML格式的trace文件,方针结束后NetAnim读取该文件显示网络拓补和节点间数据分组流等动画过程。

①首先引入相关库:

1#include "ns3/netanim-module.h"

②然后在使用Simulator语句开始仿真之前插入建立输出文件的语句:

1  AnimationInterface anim("random_walk.xml");

③运行文件,会在ns3.xx中生成xml文件 ④在终端中的ns3.xx/netanim-3.xxx路径下执行下面命令启动软件:

1./NetAnim

⑤选中生成在ns3.xx中的xml文件,即可完成可视化,在该软件上方的工具栏点击播放(▶)按钮即可看到节点的具体运动过程

5.brite

Brite是一个拓扑生成器。波士顿大学2001年开发

特点:考虑了Internet实际拓扑的多个方面,如层次性、连接度分布 • 产生的拓扑在幂律指数和路径长度等方面接近Internet的实际拓扑 • BRITE适合于大规模幂律图(即:网络的度分布服从幂律分布),它采用了Waxman模型、Barabási-Albert模型等创建AS(Autonomous System,自主系统)级、路由器级和分层拓扑。

步骤:在平面上放置节点,在节点间建立内部边(可根据参数设置,选择节点间连接概率模型,如Waxman、BA) • BRITE的使用方法:需要 单独编译,具体过程在NS-3-Model-Library.pdf中给出。 • 其他拓扑结构的使用方法:NS-3还支持从inet、orbis、RocketFuel等工具生成的拓 拓 扑文件中读取网络的拓扑结构

 1int
 2main (int argc, char *argv[])
 3{
 4...
 5/*RITE需要一个配置文件来构建它的图。默认情况下,这个例子将使用TD_ASBarabasi_RTWaxman.conf文件。
 6它结合了Barabasi的AS拓扑和Waxman的RT拓扑生成算法,形成了层次化拓扑结构。
 7在BRITE/conf_files目录中还可以找到许多其他文件*/
 8std::string confFile = "src/brite/examples/conf_files/TD_ASBarabasi_RTWaxman.conf";
 9
10...
11
12/*调用BriteTopologyHelper并传入一个BRITE配置文件和一个种子文件。这将使用BRITE来构建一个图,我们可以从中构建ns-3拓扑*/
13BriteTopologyHelper bth (confFile);
14bth.AssignStreams (3);
15
16...
17Ipv4AddressHelper address; //IPv4Helper对象
18address.SetBase ("10.0.0.0", "255.255.255.252");//基地址和子网掩码
19
20bth.BuildBriteTopology (stack); //建立拓扑,并安装指定的协议栈
21bth.AssignIpv4Addresses (address); //分配IP地址
22
23
24/*BRITE拓扑生成器生成路由器的拓扑。在这里,我们创建了两个子网络,并将其
25连接到由BRITE生成的路由器叶节点。任何NS3拓扑都可以用于连接到BRITE叶节点,
26但在这里,我们只使用一个节点*/
27
28NodeContainer client; //客户端对象
29NodeContainer server; //服务器对象
30
31client.Create (1); //创建1个客户端
32stack.Install (client);//为客户端安装协议栈
33
34//将客户端指定到生成的拓扑结构AS0的最后一个叶子节点
35int numLeafNodesInAsZero = bth.GetNLeafNodesForAs (0); 
36client.Add (bth.GetLeafNodeForAs (0, numLeafNodesInAsZero - 1));
37
38server.Create (1); //创建一个服务器
39stack.Install (server);//为服务器安装协议栈
40
41//将服务器指定到生成的拓扑结构AS1的最后一个节点
42int numLeafNodesInAsOne = bth.GetNLeafNodesForAs (1); //将服务器指定倒AS1的最后一个节点
43server.Add (bth.GetLeafNodeForAs (1, numLeafNodesInAsOne - 1));
44
45...
46
47// Run the simulator
48Simulator::Stop (Seconds (6.0));
49Simulator::Run ();
50Simulator::Destroy ();
51
52return 0;
53}

五、NS3文件操作

src目录是ns-3的源代码目录,其目录结构基本和ns-3模块相对应这些模块目录的子目录都是固定的。

  • bindings/ 绑定
  • python 语言的
  • doc/ 帮助文档
  • examples/ 应用该模块的示例代码
  • helper/ 模块对应的helper类源文件
  • model/ 模块代码的.cc和.h文件
  • test/ 模块设计者编写的模块测试代码
  • wscript wscript脚本文件,使目录下的脚本文件包含netanim模块

一些常用模块

模块 用途
core ns3内核模块,实现了ns-3的基本机制,智能指针,属性,回调,随机变量,日志,追踪,事件调度等
network 网络数据分组模块,一般仿真都会使用
Internet 实现了TCP/IP相关的协议族,IP, ARP, UDP, TCP等
applications 几种常见的应用层协议
mobility 移动模型模块,为节点添加移动属性
status 统计框架模块,方便对仿真数据的收集、分析和统计
tools 统计工具,作图工具gunplot
netanim 动画演示工具
visualizer 可视化界面工具

原文链接:https://blog.csdn.net/qq_41816035/article/details/88071765

常用命令

1ls   //列出文件夹下所有文件
2locate core-module.h     //查询这个文件的位置
3cd  A/B //修改文件目录(和windows一样)
4cd ..   //返回上一层文件目录
5cp A/B/first.cc A/C/myfirst.cc   //复制
6gedit A/C/myfirst.cc   //用文本编辑器打开文件

编译

把文件复制放到ns-3.34/scratch文件中,使用下面这行命令,ns3会自动编译该文件夹下的所有文件

1./waf

运行

1./waf --run scratch/myfirst      //运行myfirst_2.cc文件,注意命令行没有后缀
2sudo ./waf --run scratch/myfirst     //如果需要权限,加上sudo前缀

有参数时运行

文件里:

(1)创建CommandLine类对象cmd;

(2)cmd.Addvalue(属性名称,属性说明,变量)函数,添加一个可以通过命令行修改的参数

(2)cmd.Parse (argc,argv); 参数解析,将命令行输入的参数作为类CommandLine的参数进行分析。

这时再运行文件的时候使用下面的命令可以改动文件里的参数:

1./waf --run “scratch/three-gpp-http-example --SimulationTime=30”    //注意双引号,注意格式

日志

(1)日志的不同级别

NS3提供了不同详尽程度的日志级别,以帮助用户获得仿真过程的所需信息。有7个程度递增的日志级别,级别越高内容越详细,包括:

  • LOG_ERROR:记录错误信息
  • LOG_WARN:记录警告信息
  • LOG_DEBUG:记录调试信息
  • LOG_INFO:记录程序进展信息
  • LOG_FUNCTION:记录每个调用函数信息
  • LOG_LOGIC:记录每一个函数内部描述逻辑流程信息
  • LOG_ALL:记录所有信息

(2)日志的配置

A.使用LOG_LEVEL_INFO级别的日志配置 使用日志系统函数LogComponentEnable实现日志的配置。设置日志为LOG_LEVEL_INFO级别,则打开了这个日志级别和它之下的所有级别。

B.使用LOG_LEVEL_ALL级别的日志配置 上述结果只显示了基本收发信息,信息内容不够充实。在Shell界面中,可输入对环境变量NS_LOG的设置,如下:

1export NS_LOG=ThreeGppHttpServer=level_all

六、经典模型

1. 业务源模型

业务源模型重要性:在信息网络建模中,业务源的模型至关重要,准确的业务模型能够对业务中的关键特征进行表示。

不同的实际应用将产生不同的业务源类型,例如: http 业务、 P2P 业务 、话音业务 、视频业务 和计算业务等。

建模过程通常包括两步:

首先:通过适当的方法来测量关键特征,方法如:服务器日志、客户端日志、数据包跟踪等方法;

然后:在模型中表示出这些特征,例如采用马尔可夫链等方法。

业务源模型的共性特征 (层次性,多参数,协议流程分析)

层次性:基本都将业务过程分为多个不同层次,分层建模

多参数:

基本都不是单参数模型

通过对时间间隔、持续时间、数据量大小等多个量分别建模,最终达到模拟整个随机过程的目的

协议流程分析:

业务源模型往往与应用层协议密切相关,这些协议的处理流程基本都遵循一定标准,通过对标准所规定的协议流程的分析,从中划分出 确知量和真正的 随机量

直接对这些随机量进行建模,对确知量则直接通过模拟流程得到

HTTP业务

WWW业务:因特网的重要部分

WWW业务 :

网页:网络业务建模的重要模块

包括ASCII形式的超文本标记语言(HTML)

HTML:定义网页的结构和互联关系

主对象:组成网页页面的主体框架,即一个由HTML描述的文档

嵌入对象:内嵌在页面框架中的文本、声音或者图片等。

下载网页的过程:向网页的URL链接发送请求,通过HTTP 协议,与网页服务器之间建立TCP连接

面向页面的建模

面向页面的模型通常以多层结构来进行描述,包括会话级、页面级、连接级、数据包级。

HTTP参数:

会话级重要参数包括:

• 会话到达间隔

• 浏览时间

• 每个会话的页面数

页面级重要参数包括:

• 同一会话中两个连续页面间时间

• 主对象特征

• 嵌入对象特征

• 主对象解析时间

连接级重要参数包括:

• 每个页面的连接个数

• 同一页面两个连续连接的时间间隔

• 连接的大小

ns3实现

 1int
 2main (int argc, char *argv[])
 3{
 4  double simTimeSec = 300;
 5  CommandLine cmd;  //支持命令行参数功能
 6  cmd.AddValue ("SimulationTime", "Length of simulation in seconds.", simTimeSec);  //添加所支持的命令行参数
 7  cmd.Parse (argc, argv);  //命令行参数解析
 8
 9  Time::SetResolution (Time::NS);  //设置时间分辨率
10  LogComponentEnableAll (LOG_PREFIX_TIME);//log前打上时间
11  //LogComponentEnableAll (LOG_PREFIX_FUNC);
12  //LogComponentEnable ("ThreeGppHttpClient", LOG_INFO);
13  ///LogComponentEnable ("ThreeGppHttpServer", LOG_INFO);
14  LogComponentEnable ("ThreeGppHttpExample", LOG_INFO); 
15
16  // Setup two nodes
17  NodeContainer nodes;  //节点容器
18  nodes.Create (2); //创建2个节点
19
20  PointToPointHelper pointToPoint; //点对点拓扑
21  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
22  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
23//设置链路参数
24  NetDeviceContainer devices;//设备容器
25  devices = pointToPoint.Install (nodes);
26
27  InternetStackHelper stack; //协议栈
28  stack.Install (nodes); //在两个节点上安装协议栈
29
30  Ipv4AddressHelper address;
31  address.SetBase ("10.1.1.0", "255.255.255.0");//IP基地址和子网掩码
32
33  Ipv4InterfaceContainer interfaces = address.Assign (devices);为两个设备分配地址
34  Ipv4Address serverAddress = interfaces.GetAddress (1);
35
36//服务器端地址
37  // Create HTTP server helper
38  ThreeGppHttpServerHelper serverHelper (serverAddress);
39  //创建3GPP HTTP Server
40  // Install HTTP server
41  ApplicationContainer serverApps = serverHelper.Install (nodes.Get (1)); //安装Http server
42  Ptr<ThreeGppHttpServer> httpServer = serverApps.Get (0)->GetObject<ThreeGppHttpServer> (); //获得Server指针
43
44  // Example of connecting to the trace sources
45  httpServer->TraceConnectWithoutContext ("ConnectionEstablished",
46                                          MakeCallback (&ServerConnectionEstablished));
47  httpServer->TraceConnectWithoutContext ("MainObject", MakeCallback (&MainObjectGenerated));
48  httpServer->TraceConnectWithoutContext ("EmbeddedObject", MakeCallback (&EmbeddedObjectGenerated));
49  httpServer->TraceConnectWithoutContext ("Tx", MakeCallback (&ServerTx));
50
51  // Setup HTTP variables for the server
52  PointerValue varPtr;
53  httpServer->GetAttribute ("Variables", varPtr);
54  Ptr<ThreeGppHttpVariables> httpVariables = varPtr.Get<ThreeGppHttpVariables> ();
55  httpVariables->SetMainObjectSizeMean (102400); // 100kB
56  httpVariables->SetMainObjectSizeStdDev (40960); // 40kB
57//设置HTTP模型有关的变量:主对象大小均值和标准差
58  // Create HTTP client helper
59  ThreeGppHttpClientHelper clientHelper (serverAddress);
60
61  // Install HTTP client
62  ApplicationContainer clientApps = clientHelper.Install (nodes.Get (0));
63  Ptr<ThreeGppHttpClient> httpClient = clientApps.Get (0)->GetObject<ThreeGppHttpClient> ();
64//生成客户端,绑定到另一节点,并获取对象指针
65  // Example of connecting to the trace sources
66  httpClient->TraceConnectWithoutContext ("RxMainObject", MakeCallback (&ClientMainObjectReceived));
67  httpClient->TraceConnectWithoutContext ("RxEmbeddedObject", MakeCallback (&ClientEmbeddedObjectReceived));
68  httpClient->TraceConnectWithoutContext ("Rx", MakeCallback (&ClientRx));
69
70  // Stop browsing after 30 minutes
71  clientApps.Stop (Seconds (simTimeSec));
72
73  Simulator::Run ();
74  Simulator::Destroy ();
75  return 0;
76}

2.拓扑模型

固定拓扑与随机拓扑

有的网络拓扑结构是固定不变的,即固定拓扑,如点对点、总线、星形等。

有的网络拓扑与节点的地理位置密切相关,即随机拓扑,如移动通信网、自组织网络。

节点的生灭会造成网络拓扑结构的变化。

随机拓扑常常用具有某种统计特性的图来表示。图中最基本的特性包括:边的个数|E|和顶点的个数|V|

分类

①给定节点数和连接随机图构造:

在给定节点数和概率p的情况下(概率p :两个顶点之间是否存在连接将以概率p进行独立构造)

②几何随机图——Waxman 模型:

Waxman图比较适用于较小的网络模型:考虑几何距离,在该模型中,顶点随机放置于笛卡尔坐标网格。

③偏好连接模型——Barabási-Albert模型:

度越大的节点越容易被连接,该模型非常适用于因特网以及一些社交网络的建模。

① P2P拓扑模型,用于两个节点之间的点对点

②总线型拓扑模型:

采用单根数据传输线作为通信介质,所有的节点都通过相应的硬件接口直接连接到通信介质,而且能被所有其他的节点接收。

③星形拓扑模型:

各工作站以星型方式连接成网。网络有中心节点,其他节点(工作站、服务器)都与中心节点直接相连,由中心节点向目的节点发送数据,任意两个节点间的通信都需要通过中心节点。

3.运动模型

一些常见的:

(1)随机游走移动模型:一种广泛使用的模型,根据自然界中的实体以不可预测的方式移动而建立的;一种无记忆移动模式,当前运动的速度和方向完全独立于其过去的速度和方向。该模型通常被称为布朗运动模型。

(2)随机位点移动模型:是一种广泛使用的模型,与随机游走运动模型非常相似,随机位点运动模型定义了两次运动之间的暂停时间。暂停后,模型将计算新的运动形式。如果暂停时间设置为零并且速度范围选择相似,则随机位点运动模型与随机游走运动模型相同。

(3)随机方向移动模型:实体随机选择一个方向和速度。该实体基于所选择的方向和速度移动, 直至其到达仿真区域的边界。在到达边界后,该实体将停留一段预定的时间,然后选择新的方向和速度重新移动。

(4)高斯马尔科夫移动模型: 高斯马尔科夫模型具有记忆性和可变性,模型的运动可以依赖于先前运动。运动实体被分配初始速度和方向,在固定的时间间隔内对实体进行方向和速度的更新。可以定义当前运动对先前运动的依赖程度,可以为实体指定运动的平均速度。为了避免与模拟区域的边界发生碰撞,当实体接近边界时,可以调整实体方向:当实体到边界的距离小于一定值时,使实体离开边界。

(5)曼哈顿模型:广泛应用的街区或者高速公路移动模型,实体沿着双向的街道和十字路口移动。需定义速度、加速度、安全距离,实体以一定的概率沿着街道或者十字路口移动。

(6)追踪移动模型(Pursue Mobility):一种群体移动模型,其中一组移动实体正在追踪单个参考实体。参考实体使用的是实体移动模型,例如随机游走移动模型。其他实体都追踪参考实体,但是在它们的移动方向上增加了较小的偏差。在该模型中模拟了加速度

4.信道模型

信道模型的分类:

  • 波形信道:用于链路级仿真,直接对电磁波传播所带来的多径传播等效应进行建模。

  • 离散信道:离散符号输入-输出信道模型

    例如:评估信源编译码器性能时,可以把从信源编码输出到信源译码输入之间部分的误码分布作为信道模型。

  • 抽象信道:对信道所关注的层次上反映出来的一些指标进行抽象:误码率、误码块率、可达性、最高吞吐率。

原文链接:https://blog.csdn.net/jj123456879/article/details/121963380