- 下载n s3安装包(https://www.nsnam.org/):
笔者下载的是ns-allinone-3.25.tar.bz2
- Build essential, 安装 gcc, g++, python, python-dev 等:
进入命令行,输入如下命令:
或者:
- 编译NS3软件包:
1)用 cd命令转到ns-allinone-3.25.tar.bz2的文件夹目录下
2)解压缩包: tar xvf ns-allinone-3.25.tar.bz2
3) cd进入解压得到的文件夹中运行命令:./build.py --enable-examples --enable-tests命令,对下载的源代码进行整体编译。
编译脚本开始编译下载的ns3时,会看到大量常见的编译器输入信息。最后会看到编译成功的消息:
编译完成之后,在当前目录(ns-allinone-3.25)下会产生一个名为ns-3.25/的目录,切换到该目录下:
cd ns-3.25
4.对编译的正确性进行测试:
通过运行“./test.py -c core”脚本进行ns-3软件包的正确性测试:
./test.py -c core
这些测试可以被waf并行执行,最后可以看到如下的结果:
用户通常可以运行此命令来检查NS3软件包是否正确编译了。
5.运行第一个脚本:
我们通常使用waf运行脚本程序。在正确编译了NS3软件包之后,如果要运行一个程序,只需在waf后加入--run选项即可。让我们在ns-3环境下运行常见的Hello Simulator程序,该程序就相当于学习一门语言时的Hello World程序:
./waf --run hello-simulator
Waf会首先检查程序正确编译了,而且还可以根据需要重新执行编译。Waf执行了此程序,并输出如下信息:
如果没有看到输出“Hello Simulator”,说明你是在优化编译模式下进行的编译,在优化编译模式下,默认将关闭控制台输出。可以通过以下命令:
./waf clean
./waf -d debug --enable-examples --enable-tests configure
在调试编译模式下进行重新编译。
到现在为止,我们顺利的下载编译了NS3软件包,并通过测试和运行Hello Simulator脚本程序来验证了软件包正确性。
NS3使用说明:
- 脚本分析:
下面通过ns-3.25/example/tutorial目录下的second.cc进行使用说明。这个脚本的拓扑分布如下图所示,n0和n1实现点到点通信,n1~n4是个csma有线局域网。网络可以实现n0经由n1,和n4进行通信。
各代码段的注释如下:
using namespace ns3; //声明命名空间
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");//定义日志组件
int
main (int argc, char *argv[])
{
bool verbose = true;//定义bool变量用于决定是否开启日志组件,默认开启
uint32_t nCsma = 3;//变量,用于定义csma网络中有多少个node
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
//命令行参数,设置是否开启logging
cmd.Parse (argc,argv);
if (verbose)
{ //使两个日志组件生效
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma = nCsma == 0 ? 1 : nCsma;
//********网络拓扑部分********//
//p2p链路的两个节点创建
NodeContainer p2pNodes;
p2pNodes.Create (2);
//创建csma网络节点
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));//将p2p节点1加到csma网络中
csmaNodes.Create (nCsma);
//设置p2p传输速率和信道延迟
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
//安装p2p网卡到p2p网络节点
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
//设置csma传输速率和信道延迟,注意传输速率有channel指定,而非device属性。(CSMA不允许同一信道上有多个不同数据率的设备)
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
//安装协议
InternetStackHelper stack;
stack.Install (p2pNodes.Get (0));//p2p的n0节点,n1节点在csma网络中安装协议栈
stack.Install (csmaNodes);
//设置IP地址
Ipv4AddressHelper address;
//从10.1.1.0开始以子网掩码为255.255.255.0分配地址
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);
//********应用程序部分********//
UdpEchoServerHelper echoServer (9);//服务器端口号
//将server服务器安装在csma网络的n4节点。假定nCsma=3
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);//设定远程服务器的IP地址和端口号
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));// 模拟期间所能发送的最大数据包个数
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); //两个数据包之间要等待多长时间
echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); //数据包大小
ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
//********建立网络路由********//
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
//********开启pcap追踪********//
//开启p2pHelper,csmaHelper类对象的pcap
pointToPoint.EnablePcapAll ("second");
csma.EnablePcap ("second", csmaDevices.Get (1), true);
Simulator::Run (); //运行模拟器
Simulator::Destroy (); //清理
return 0;
}
其实,我们只发送了一个数据包(MaxPackets属性被设置为1),在此之后,那个被单独的客户端应答请求所引发的连锁反应会停止,并且模拟器会进入空闲状态。当这发生时,剩下的事件就是服务端和客户端的Stop事件。当这些事件被执行后,就没有事件可执行了,函数Simulator::Run会返回。整个模拟过程就结束了。
- 运行脚本程序:
- 复制examples/tutorial/second.cc文件到scratch目录下,并改名为mysecond.cc文件:
cp examples/tutorial/first.cc scratch/mysecond.cc
- 使用waf命令来编译脚本:
./waf
- 运行该例子:
./waf –run scratch/mysecond
得到输出如下,说明通讯成功: