NS3 介绍
1. ns-3的目录结构
打开ns-3.33文件,将会看到这样的情况,下面依次介绍目录中文件的功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UG88xFuz-1627476544969)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728144225982.png)]
-
waf 是Python开发的编译工具 -
scratch一般存放目录脚本文件,该目录是ns-3默认的脚本存放目录,使用waf编译运行脚本文件时,可以不加目录scratch,如果脚本文件在其他目录下需要在文件名前加入目录。 -
examples 是ns-3提供的如何使用ns-3的例子,包含很多模块的使用,如能量、路由、无线网络等等。 -
doc存放帮助目录。可以通过waf将ns-3在线帮助文档doxygen编译到本地的doc目录下,方便离线阅读学习ns-3代码。可以使用如下命令去编译本地Doxygen文件 ./waf-doxygen
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2l4fM5wj-1627476544972)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728144941237.png)]
build是ns-3编译目录,包含编译文件时所需要的共享库和头文件。
src是ns-3源代码目录,其目录如图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdBQJquH-1627476544973)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728145143822.png)]
每一个都是一个模块目录,我们随便打开一个长成这样:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WOSIm7nN-1627476544975)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728145312549.png)]
- wscript文件结构是固定的,用来注册模块中包含的源代码和其他模块情况。
- model文件存放模块代码的.cc 和.h文件。(高级应用者需要开发一个新的路由协议或者设计一个新的移动模型或能量模型)
- helper目录存放的是模块对应的helper类代码的源文件。
- test目录存放模块设计者编写的模块测试代码。
- examples存放的是应用该模块的示例代码 (初级应用者利用NS-3现有模块编写脚本文件进行网络仿真,比如使用常规协议栈中的协议配置一个有线或者无线局域网络)
- doc是帮助文件
- bingings是模块用来绑定Python语言用的。
(2)了解ns-3成功编译的模块
当编译成功时,就会出现如下安装成功的模块。当然也有安装不成功的,没关系。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1rXiabfs-1627476544976)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728151347717.png)]
core:ns-3的内核模块,实现了ns-3的基本机制。如智能指针Ptr,属性attribute,回调callback,随机变量random variable,日志logging,追踪tracing,事件调度event scheduler。(第五章)
network: 网络数据分组(packet)模块。(6.1)
Internet:实现了关于TCP/IPv4和IPv6的相关协议族,包括IPv4、IPv6、ARP、UPP、TCP、邻居发现和其他相关协议。(6.2)
application: 常用的应用层协议(6.4)
mobility:移动模型模块(6.5详细介绍了节点移动模型)
topology-read:读取指定轨迹文件数据,按照指定格式生成相应的网络拓扑。
energy:能量管理模块,移动设备的能量问题(6.6)
status:统计框架模块,方便ns-3仿真的数据搜集、统计、分析(4.3)
tools: 统计工具,包括统计作图工具gnuplot的接口和使用(4.4)
visualizer:可视化界面工具PyViz (4.1.1)
netanim:动画演示工具NetAnim(4.2.2)
propagation:传播模型模块
flow-monitor:流量监控模块
下面是典型的网络模块,包括网络前沿研究领域如LTE和UAN:
point-to-point:实现了点到点的通信(6.3.1)
CSMA 实现了基于IEEE802.3的以太网络,包括MAC层、物理层和媒体信道(6.3.2)
Wi-Fi如何实现802.11a/b/g的无线网络
mesh基于IEEE802.11s的无线mesh网络
wimax实现了基于IEEE802.16标准的无线城域网络
LTE (long term evolution)是第三代合作伙伴计划
UAN: ns-3的水声通信网络模块,可以仿真水下网络真实场景,实现了信道、物理层和MAC层
2. 如何运行first.cc (这是一个example/tutorial中的示例)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S4G9DSoQ-1627476544976)(C:\Users\Chris Xie\AppData\Roaming\Typora\typora-user-images\image-20210728195533582.png)]
firstly.cc非常简单,就是配置两个node,然后建立链接。
-
eclipse中把firstly文件复制到scratch下(以防万一,否则报错),并在eclipse中打开这段代码,下面展示代码和打开界面 -
然后简单编译一下,看看能不能过(其实我也知道为啥,也许是方便看写的程序错不错)。 -
然后运行一下,在terminal上cd到ns3.33文件,然后输入(这个时候就知道复制到scratch中是很必要的) ./waf --run scratch/first
运行结果:
3. 分析一下first.cc的代码
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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"
// Default Network Topology
//
// 10.1.1.0
// n0 -------------- n1
// point-to-point
//
using namespace ns3;
//定义一个人LogComponent类型的对象
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample"); //日志:#define static ns3::LogComponent g_log=NS3::LogComponent(name);
int
main (int argc, char *argv[])
{
CommandLine cmd (__FILE__);
cmd.Parse (argc, argv);
Time::SetResolution (Time::NS);
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO); //让日志组件生效
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
NodeContainer nodes; //生成网络节点容器
nodes.Create (2); //容器里放了两个节点:0是客户端,1是服务端
PointToPointHelper pointToPoint; //PointToPointHelper类:负责设置网络设备和信道属性,并通过install方法把设备安装到节点中
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); //设置传输速率 : DataRate对应PointToPointHelper的一个性质,可以通过SetDeviceAttribute()函数直接设置PointToPointNetDevice=5Mbps
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); //设置传输信道延时:Delay对应子类PointToPointChannel的Delay性质
NetDeviceContainer devices; //将节点和设备安装好,存入devices
devices = pointToPoint.Install (nodes);
//安装协议栈:类InternetStackHelper会为每一个节点容器中的节点安装一个网络协议栈,主要是IP层
InternetStackHelper stack;
stack.Install (nodes); //给节点分配网络协议栈
//Ipv4AddressHelper类会节点上的设备IP地址。
Ipv4AddressHelper address; /
address.SetBase ("10.1.1.0", "255.255.255.0"); //IP地址和子网掩码:告诉从10.1.1.0开始,以子网掩码为255.255.255.0分配地址,地址分配默认是从1开始单调增长,所以在这个基础上第一个分配的地址是10.1.1.1,紧接着是10.1.1.2
//将地址和设备关联起来
Ipv4InterfaceContainer interfaces = address.Assign (devices);
//安装服务器端应用程序、设置端口号:
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1)); //端口号给node1
serverApps.Start (Seconds (1.0)); //让echo服务应用在1s时开始,在10s时停止
serverApps.Stop (Seconds (10.0));
//配服务
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9); //需要一个udpEchoClientHelper来管理UdpEchoClientApplication
echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); //MaxPacket最大数据分组个数
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); //Interval在两个数据分组之间要等待多长时间
echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); //数据分组要承担多少数据
//应用给node
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
//让模拟器运行起来
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
1)日志(我暂且还没学到,下面应该会详细讲这是个什么东西)
-
首先是日志 //定义一个人LogComponent类型的对象
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample"); //日志:#define static ns3::LogComponent g_log=NS3::LogComponent(name);
-
然后是主函数int main() -
主函数首先要开启日志(可以看到是对Application生效) LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO); //让日志组件生效
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
2)创建节点Node(NodeContainer类)
-
node是代表主机的一个东西,基本是一个裸机,一切application和组件都要在node上配置 NodeContainer nodes; //生成网络节点容器
nodes.Create (2); //容器里放了两个节点:0是客户端,1是服务端
3)创建信道(pointTopointHelper类)
-
PointToPointHelper类:负责设置网络设备和信道属性 PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
//可以把DataRate和Delay看成对象的一个性质
4)Node和Channel都成为device,然后就想办法把它俩组装到一起叫做NetDeviceContainer类
-
组装之后就变了一个新的东西叫做NetDeviceContainer类,代表node和channel的组合 NetDeviceContainer devices; //将节点和设备安装好,存入devices
devices = pointToPoint.Install (nodes);
5) 给node以IP地址(IPv4AddressHelper类)
-
批量分配IP地址 Ipv4AddressHelper address; address.SetBase ("10.1.1.0", "255.255.255.0"); //IP地址和子网掩码:告诉从10.1.1.0开始,以子网掩码为255.255.255.0分配地址,地址分配默认是从1开始单调增长,所以在这个基础上第一个分配的地址是10.1.1.1,紧接着是10.1.1.2
6)把IP地址和设备装在一起(IPv4InterfaceContainer)
-
拥有地址的devices,构成新类叫做interfaces Ipv4InterfaceContainer interfaces = address.Assign (devices);
7) 配置服务(主要这里讲两个application:UdpEchoServerHelper类和UdpEchoClientHelper类)
-
echo成为回声,就是收到什么就发送什么
看上面例子,就知道client先发送,然后server收到了client发送的1024 bytes,马上就发送一个1024 bytes给client。
让我们看看怎么配置这个应用的:
1)首先开一个服务,给server,设置端口号为9(注意这里指server给client开放的端口号是9,证明client 要发送到server的9号端口)
UdpEchoServerHelper echoServer (9);
2) 然后,把这个服务给node1 ,称为serverApps (出现一个新的类ApplicationContainer),并且开放application的时间:start和end
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1)); //端口号给node1 serverApps.Start (Seconds (1.0)); //让echo服务应用在1s时开始,在10s时停止 serverApps.Stop (Seconds (10.0));
3) 开一个服务给node0,告诉client给10.1.1.1(Server)发送,发送给Server的9号端口
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9); //需要一个udpEchoClientHelper来管理UdpEchoClientApplication
4) 设置传输包的大小和时隙
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9); //需要一个udpEchoClientHelper来管理UdpEchoClientApplication echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); //MaxPacket最大数据分组个数 echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); //Interval在两个数据分组之间要等待多长时间 echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); //数据分组要承担多少数据
5) 把这个应用给node0配置,并且设置开始和结束时间
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0)); clientApps.Start (Seconds (2.0)); clientApps.Stop (Seconds (10.0));
8)让模拟器运行起来
Simulator::Run (); Simulator::Destroy (); return 0;
问题:为什么是client先给Server发送包?这个是Udp协议,如果是TCP协议(三次握手)??
|