另一方面,OTcl是解释执行的,用OTcl进行模拟配置,可以在不必重新编译的情况下随意修改模拟参数和模拟过程,提高了模拟的效率。 (5)同时,这种分裂对象模型增强了构件库的可扩展性和可组合性,用户通常只需要编写OTcl脚本就可以把一些构件组合起来,成为一个“宏对象”。(例如,节点对象就是由一些分类器、复用器、链路等对象组合而成的)
(6)分裂对象模型也起到了抽象的作用,它对用户屏蔽了功能实现的细节。用户通过OTcl进行模拟配置,很多情况下只需要了解构件的使用和配置接口就可以了,而不需要了解这些构件的功能是如何实现的。
(7)实践证明,较好地掌握OTcl语言对于深入学习NS,阅读其他研究者公布的脚本代码以及在自己使用NS过程中减少bug,缩短调试周期等方面都是大有裨益的。
[4] 开放的源代码NS是免费的,开放源代码的。(这是一个好的网络模拟器的生命力之所在)
第四讲
使用NS进行网络模拟的方法和一般过程 [1] NS模拟的两个层次
两个层次为:
(1)基于OTcl编程的层次
利用NS已有的网络元素实现模拟,无需对NS本身进行任何修改,只要编写OTcl脚本。 (2)基于C++和OTcl编程的层次
如果NS中没有所需的网络元素,就需要首先对NS扩展,添加你所需要的网络元素。这就需要利用前面所提到的分裂对象模型, 添加新的C++类和OTcl类,然后再编写OTcl脚本。 [2] 进行一次模拟的步骤假设用户已经完成对NS的扩展或者NS所包含的构件已经满足了要求。
(1)开始编写OTcl脚本。
首先配置模拟网络拓扑结构,此时可以确定链路的基本特性,如延迟、带宽和丢失策略等。 (2)建立协议代理,包括端设备的协议绑定和通信业务量模型的建立。 (3)配置业务量模型的参数,从而确定网络上的业务量分布。
(4)设置Trace对象。Trace对象能够把模拟过程中发生的特定类型的事件记录在trace文件中。NS通过trace文件来保存整个模拟过称。仿真完成后,用户可以对trace文件进行分析研究。
(5)编写其他的辅助过程,设定模拟结束时间,至此OTcl脚本编写完成。 (6)用NS解释执行刚才编写的OTcl脚本。 (7)对trace文件进行分析,得出有用的数据。也可以用Nam等工具观看网络模拟运行过程。 (8)调整配置拓扑结构和业务量模型,重新进行上述模拟过程。
第五讲
(一)NS方法学
NS的优势在于它的内容非常丰富,但同时,这也是它的劣势。它是一个庞大的系统,有一个相对陡峭的起始学习曲线。也就是说初学者在入门时面临的困难最大。所以掌握正确的方
法,具备正确的观念,对于学习NS来说尤为重要。 (1)掌握原理。
NS使用者应该做到对NS的离散事件模拟机制以及分裂对象模型非常清楚。这是进一步深入学习和使用NS的基础。 (2)牢记节点结构。
节点是NS中最重要的一个构件。一个节点是由分类器(Classifier)、复用器(dmux_)、代理(Agent)、链路(link)、路由器等更基本的构件组合而成的。有线网络节点和无线网络节点的结构是不同的。不同节点用链路连接起来,就构成了网络,因此使用者应该对节点结构非常熟悉。这样,用户对整个网络模拟运行过程就会比较清楚,也会知道需要添加的功能该在哪部分实现。
图:单播节点的内部结构
图:多播节点的内部结构
(3)学会查手册但不依赖于手册。
NS手册有一些不足之处,但是它仍然是目前关于NS的最全面的资料。当用户具备了一定的基础之后,再去查看NS手册,就会发现从中还是可以学到很多东西的。用户可以看到从开发者的角度对用户所感兴趣的构件的内部原理是怎样理解的。至于具体的编程接口,不应该依赖于手册上的说明,在很多情况下应该去直接查看源代码。这样就会对各个对象之间相互的接口关系非常清楚了。
(4)用户应该对主要的网络构件的功能都有所了解。 当需要实现用户自己的网络模拟模型时,就会知道哪部分可以利用现成的,而哪部分是需要自己做的,以及放在哪里实现最合适。这样才不会走弯路,才能设计出工作量最少的、最合理的模拟方案。 (5)常看源代码。
NS是开放源代码的软件。用户应该经常地深入到NS的源代码中去,包括其他研究者贡献的源代码和脚本。这是深入学习NS的必由之路。特别是当用户扩展NS,实现新的协议模块时,用户可以从NS本身的源代码以及其他研究者的贡献中借鉴很多经验。
(二)运行NS和nam以及第一个Tcl脚本
[1] 运行NS
运行NS有两种方式:
(1)输入命令“ns
(2)输入命令“ns”,进入NS的命令行环境,然后直接输入各种指令来交互式的运行NS。 [2] 运行nam
nam是一个动画演示程序,它可以演示整个模拟的过程。nam的动画是按照nam-trace文件的内容进行的,nam-trace文件中记录了整个模拟过程的各个细节,由NS在执行模拟的同时产生,在NS的模拟过程结束后,nam就可以调用nam-trace文件来演示模拟的过程。 [3] 第一个Tcl脚本
新建一个名为example.tcl的文件,可以用任何一个文本编辑器对它进行编辑。下面是example.tcl的内容:
[python]
? ? ?
set ns [new Simulator] ;#建一个Simulator对象的实例并把它赋值给变量ns。
set tracefd [open example1.tr w] ;#打开一个名为example1.tr的文件,用来记录模拟
过程的trace数据, ? ? ?
$ns trace-all $tracefd ;#变量tracefd指向该文件;
set namtracefd [open example1.nam w];#打开一个名为example1.nam的文件,用来记录 nam的trace数据,变量namtracefd指向该文件。 ? ? ?
$ns namtrace-all $namtracefd ;
?? proc finish {} { ;#建立一个名为finish的过程(procedure),用来关闭两个trace文件, ?? global ns tracefd namtracefd ;#并调用nam程序。 ?? $ns flush-trace ?? close $tracefd ?? close $namtracefd ?? exec nam example1.nam & ?? exit 0 ?? } ??
?? set n0 [$ns node] ;#新建两个node(节点)并分别赋值给n0和n1。 ??
?? set n1 [$ns node] ??
?? $ns duplex-link $n0 $n1 1Mb 10ms DropTail ;#在n0和n1间建立一条双向的link(链路),该链路的带宽为1Mbps,延迟为10ms,队列类型为DropTail(丢尾队列)。 ??
?? set udp0 [new Agent/UDP] ;#新建一个UDP Agent并把它绑定到n0上。 ??
?? $ns attach-agent $n0 $udp0 ??
?? set cbr0 [new Application/Traffic/CBR];#新建一个CBR(Constant Bit Rate)流量发生器(traffic generator 业务产生器)。 ??
?? $cbr0 set packetSize_ 500 ;#设定分组大小为500Byte,发送间隔为5ms(即每秒发送200个分组), ??
?? $cbr0 set interval_ 0.005 ;#然后把它绑定到udp0上。 ??
?? $cbr0 attach-agent $udp0 ?? ??
?? set null0 [new Agent/Null] ;#新建一个Null Agent并把它绑定到n1上,Null是一种数据接收器,对接收到的数据不进行处理直接丢弃,Null Agent常与UDP Agent配合使用。 ??
?? $ns attach-agent $n1 $null0 ;#将Null Agent 绑定到n1上(traffic sink)。 ??
?? $ns connect $udp0 $null0 ;#将udp0和null0这两个Agent连接起来。 ??
?? $ns at 0.5 \ ;#告知Simulator对象在0.5s时启动cbr0(开始发送数据),
??
?? $ns at 4.5 \ ;#在4.5s时停止cbr0(停止发送数据)。 ?? ??
?? $ns at 5.0 \ ;#告知Simulator对象在5.0s时调用finish过程(procedure)。 ?? ??
?? $ns run ;#运行脚本,开始模拟
第六讲
NS2的离散事件调度机制
[1] Simulator类在NS2中,每个网络模拟过程需要一个类对整个过程进行控制和管理,这个类就是模拟器类(Simulator类)。 注意:
(1)整个模拟过程可以看作是对模拟器类对象的操作; (2)模拟器类是一个解释类,没有相应的编译类,封装了节点(node)、链路(link)、代理(agent)、数据分组格式等。
(3)整个模拟过程从创建一个模拟器类对象开始,通过调用这个对象的各种过程实现:创建节点、构建拓扑结构图、对模拟的各个方面进行配置、定义事件、根据定义的事件模拟整个网络的运行等。
创建一个模拟器类对象:
set ns [new Simulator] ;#新建一个Simulator对象ns(后面要使用这个ns对象,必须在前面加$)
与此同时完成了下列一系列的初始化操作: (a)初始化分组格式(调用create_packetformat);
(b)创建一个事件调度器(scheduler,缺省为calendar scheduler即时间队列式调度器); (c)创建一个空代理(null agent);
[2] NS2的事件和事件调度器 NS2是一个事件驱动的模拟器。 注意:
(1)一个NS2事件通常包含两个部分:(a)事件的触发时间;(b)用来处理事件的功能函数的句柄;
NS2模拟器内部at过程的主要功能是在特定的时间调用事件处理函数处理事件。 例如:
#下面这段Tcl代码首先创建了模拟器对象ns,由事件调度器在5秒时,调用执行handle_fun函数
set ns [new Simulator] $ns at 5.0 \ $ns run