快乐虾
http://blog.csdn.net/lights_joy/
欢迎转载,但请保留作者信息
学习一下ns中的第一个示例脚本,first.py,这个示例模拟一个Echo服务和客户端之间的通信。
1.1 导入所需要的库
ns3的每一个模块都有一个对应的用C++开发的dll,在python下也有一个相应的模块,使用前必须先导入所需要的模块:
import ns.applications
import ns.core
import ns.internet
import ns.network
import ns.point_to_point
import ns.netanim
1.2 创建节点
NS3中的一个节点代表一台能够加入诸如协议栈,应用以及外设卡等等东西的计算机。在first.py中使用下面的python语句可以创建我们需要的节点:
nodes= ns.network.NodeContainer()
nodes.Create(2)
这里的NodeContainer提供了一种简便的方式来创建、管理和使用任何节点对象,我们用这些节点来运行模拟器。
1.3 构建拓扑
上面的脚本中仅仅创建了所需要的两个节点,但他们所代表的节点什么都没有做。构建拓扑的下一步是把我们的节点连接到一个网络中。我们所支持的最简单的网络形式是一个在两个节点之间单独的point-to-point连接。我们在此会构建一个此类连接。
pointToPoint= ns.point_to_point.PointToPointHelper()
pointToPoint.SetDeviceAttribute("DataRate",ns.core.StringValue("5Mbps"))
pointToPoint.SetChannelAttribute("Delay",ns.core.StringValue("2ms"))
devices= pointToPoint.Install(nodes)
这里的DataRate和Delay是这个点对点连接的两个属性。
在Install之后可以得到一个NetDeviceContainer对象。
此时我们得到了两个节点,每一个节点安装了点到点网络设备,在它们之间是一个点到点信道。两个设备会被配置在一个有2毫秒传输延时的信道上以5M比特每秒的速率传输数据。
1.4 安装协议栈
我们现在已经配置了节点和设备,但是我们还没有在节点上安装任何协议栈。下面两行代码完成这个任务:
stack= ns.internet.InternetStackHelper()
stack.Install(nodes)
InternetStackHelper 是一个安装PointToPointHelper对象和点到点网络设备的网络协议栈的拓扑生成器类。其中Install()方法以一个NodeContainer 对象做为一个参数,当它被执行后,它会为每一个节点容器中的节点安装一个网络协议栈(TCP,UDP,IP等等)。
1.5 配置IP及MAC
下面我们需要为节点上的设备设置IP地址。
NS3提供了一个拓扑生成器来管理IP地址的分配。当执行实际的地址分配时唯一用户可见的API是设置基IP地址和子网掩码。
下面两行代码:
address= ns.internet.Ipv4AddressHelper()
address.SetBase(ns.network.Ipv4Address("10.1.1.0"),
ns.network.Ipv4Mask("255.255.255.0"))
声明了一个地址生成器对象,并且告诉它应该开始从10.1.1.0开始以子网掩码为255.255.255.0分配地址。地址分配默认是从1开始并单调的增长,所以在这个基础上第一个分配的地址会是10.1.1.1,紧跟着是10.1.1.2等等。
下面一行代码:
interfaces= address.Assign(devices)
完成了真正的地址配置,此时我们可以得到一个Ipv4Interface对象。
在ns-3中我们使用Ipv4Interface对象将一个IP地址同一个设备关联起来。正如我们有时候需要一个被生成器创建的网络设备列表一样,我们有时候需要一个Ipv4Interface对象的列表。Ipv4InterfaceContainer提供了这样的功能。
现在我们有了一个安装了协议栈,配置了IP地址类的点到点的网络。这时我们所要做的事情是运用它来产生数据通信。
1.6 Echo服务
下面的代码在节点上设置一个UDP 回显服务应用。
echoServer= ns.applications.UdpEchoServerHelper(9)
serverApps= echoServer.Install(nodes.Get(1))
serverApps.Start(ns.core.Seconds(1.0))
serverApps.Stop(ns.core.Seconds(10.0))
上面代码中的第一行构造了一个UdpEchoServerHelper对象。这是一个用来帮助创建真正应用的对象。同其它生成器对象类似,UdpEchoServerHelper对象有一个Install方法。实际上是这个方法的执行,才初始化回显服务器的应用,并将应用连接到一个节点上去。安装会返回一个容器,这个容器中包含了指向所有被生成器创建的应用指针。
应用对象需要一个时间参数来“开始”产生数据通信并且可能在一个可选的时间点“停止”。我们提供了开始和停止的两个参数。这些时间点是用ApplicationContainer的方法Start和Stop来设置的。
1.7 EchoClient
echo客户端应用的设置与回显服务器端类似。也有一个UdpEchoClientHelper来管理UdpEchoClientApplication。
echoClient= ns.applications.UdpEchoClientHelper(interfaces.GetAddress(1),9)
echoClient.SetAttribute("MaxPackets",ns.core.UintegerValue(2))
echoClient.SetAttribute("Interval",ns.core.TimeValue(ns.core.Seconds(1.0)))
echoClient.SetAttribute("PacketSize",ns.core.UintegerValue(1024))
clientApps= echoClient.Install(nodes.Get(0))
clientApps.Start(ns.core.Seconds(2.0))
clientApps.Stop(ns.core.Seconds(10.0))
对于echo客户端,我们需要设置五个不同的属性。首先两个属性是在UdpEchoClientHelper的构建过程中被设置的。按照生成器的构造函数的格式,我们把”RemoteAdress”和”RemotePort”属性传递给了生成器(实际上是作为生成器构造函数的两个必须参数传递的)。
回忆一下我们使用Ipv4InterfaceContainer来追踪我们配置给设备的IP地址。在界面容器中位置零的界面对象将会和在节点容器中的位置零的节点对象对应。同样在界面容器中位置一的界面对象将会和在节点容器中的位置一的节点对象对应。所以,在上面的第一行代码中,我们创建了一个生成器并告诉它设置客户端的远端地址为服务器节点的IP地址。我们同样告诉它准备发送第二个数据包到端口9。那个“MaxPackets”属性告诉客户端我们所允许它在模拟期间所能发送的最大数据包个数。“Interval”属性告诉客户端在两个数据包之间要等待多长时间,而“PacketSize”属性告诉客户端它的数据包应该承载多少数据。本例中,我们让客户端发送一个1024字节的数据包。 正如echo服务端一样,我们告诉echo客户端何时来开始和停止,但是这里我们使客户端在服务端生效1s后才开始(在模拟器中时间2s的时候)。
1.8 开始仿真
下面我们所需要做的就是运行模拟器,这是用全局函数Simulator.Run.来做到的
ns.core.Simulator.Run()
ns.core.Simulator.Destroy()
当我们调用了如下方法时:
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
...
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
实际上我们是在模拟器中1.0秒,2.0秒,和10.0时预设了事件的发生。
当Simulator::Run被调用时,系统会开始遍历预设事件的列表并执行。
首先它会在1.0s时运行事件,这个事件会使echo服务端应用生效(这个事件会预设更多的其他事件)。接下来仿真器会运行在t=2.0秒时的事件,即让echo客户端应用开始。同样的,这个事件可能会预定更多的其他事件。
在echo客户端应用中的开始事件的执行会通过给服务端传送一个数据包来开始仿真的数据传送阶段。发送一个数据包给服务端会引发一系列更多的事件。这些事件会被预设在此事件之后,并根据我们已经在脚本中设定的时间参数来执行数据包的应答。
其实,我们只发送了一个数据包,在此之后,那个被单独的客户端应答请求所引发的连锁反应会停止,并且模拟器会进入空闲状态。当这发生时,生下来的事件就是服务端和客户端的Stop事件。当这些事件被执行后,就没有将来的事件来执行了,函数Simulator::Run会返回。整个模拟过程就结束了。
下面剩下的事情就是清理了。这个通过调用全局函数Simulator::Destroy来完成。当生成器函数(或者低级的ns-3代码)被执行后,生成器安排的钩子函数就被插入到模拟器中来销毁所有被创建的对象。你自己并不需要追踪任何对象,你所需要做的仅仅是调用Simulator::Destroy并且退出。ns-3系统会帮你料理这些繁杂的任务。
??
版权声明:本文为博主原创文章,未经博主允许不得转载。