admin 管理员组文章数量: 887021
2024年2月25日发(作者:in the past翻译)
基于OMNET++的tictoc仿真实验报告
一、 实验原理简介
1.1 OMNET++简介
OMNET++是面向对象的离散事件仿真工具,它是由布达佩斯大学通信工程系开发的一个开源的、基于组件的、模块化的开放仿真平台,具有强大的图形用户界面接口和嵌入式仿真内核。OMNeT++可以用来仿真任何离散事件的系统,包括仿真通信协议、计算机网络、并行系统、多处理器系统和分布式系统。它能够建立目前几乎所有网络对象的基本模型之间的互联,并且使复杂的网信通信和拓扑结构得到容易而正确的仿真。
1.2 OMNeT++特性
OMNeT++在描述模型、定义网络拓扑、实现模型、跟踪支持、调试、性能等多方面都显示出强大的优势。与同属于非商业软件的NS-2[61相比,OMNET++具有更加突出的特性。①编程仿真能力和可移植性。OMNeT++和NS-2在编程能力方面的功能都很强大。OMNeT++可以在Windows系统和Linux系统等多种操作系统上运行,它生成的仿真程序是可携带的,可以独立运行于多种操作平台之上。OMNeT++提供NED(Network Description)和C++两种语言来建模仿真。其中,OMNeT++用NED来描述仿真模型的拓扑结构,它非常简单,但是具有非常强大的拓扑定义功能,可以定义模块、链路和网络。NED还可以实现动态加载,便于更新仿真模型的拓扑结构;C++用来实现模型的仿真和消息的处理等功能。而且NED文件可以编译为C++代码,连接到仿真程序中。可以说,OMNeT++仿真环境是用C++实现的。NS-2只能运行在Linux环境中,它使用OTcl和C++两种建模仿真语言,它生成的仿真程序不具备可携带性。②可仿真模型的范围。OMNeT++可以支持TCP/IP、SCSI和FDDI等多种协议模型,而NS-2只能支持基于TCP/IP的协议模型。③仿真效率。OMNeT++支持模块化仿真模型,模块可以灵活地组合,还可以多次使用。它还支持使用参量,可以在不修改源代码和不重新编译的情况下。直接设置参量,对不同条件下的网络模型进行仿真,因此比NS-2具有更好的仿真效率。④仿真结果输出的性能。OMNeT++提供强大完善
的图形用户界面,具有模块输出窗口、监测器和自动生成动画3个输出工具,可以动态地观察仿真程序的运行情况,而且内存消耗小、速度快。也具有自动生成
动画效果的功能,但没有模块输出窗口和监测器。可以看出,MNET++具有更强大的计算机网络模型仿真能力,OMNET++更适用于各种计算机网络模型的仿真。
2、TICTOC仿真步骤
首先,让我们来考虑一个包含两个节点的“网络”,节点所做的事非常简单就是:一个节点创建数据包,然后这两个节点将该数据包来回传送,(就像打乒乓球一样),我们把这两个节点分别称之为“tic”和“toc”。
从零开始——实现你的第一个仿真的步骤:
1. 创建一个工作目录,取名tictoc,并切换到该目录。(译者注:路径名不能含空格和中文字符)。
2. 创建一个拓扑文件来描述该样例网络。拓扑文件是标识网络节点及其链路的文本文件,有两种编辑方式,可视化以及代码方式。我们对它取名为:、
3. 现在我们需要实现简单模块Txc1 的功能,通过写一个C++文件()来完成。
在初始化函数中我们创建了一个消息对象(cMessage)并通过输出门out 对外发送。因为该门连接到其他模块的输入门,所以仿真内核将会把handleMessage()函数参数中携带的这个消息传递给其他模块。该消息将会在NED 文件中指派给链路的100ms 传播延迟后到达。其他模块收到后同样将该消息送回(仍然经过100ms 的延迟),所以整个过程就像一个永不停歇的乒乓球一样。
在 OMNeT++中,所有的消息(数据包、帧、任务等)和事件(定时、超时)都通过cMessage对象(或它的子类)描述。一旦它们被送出或者被调度,就会被仿真内核放在”已调度事件”和” 未来事件”列表中,直到时钟来临,再通过handleMessage()传递到相关模块。
要注意到在本仿真样例中,并没有内建停止条件,也就是说,仿真会一直进行下去。你可以从GUI 图形界面停止它。
4.使用opp_makemake命令创建Makefile文件。Windows+msvc环境用户使用opp_nmakemake命令创建文件。
5.使用make命令编译。Windows+msvc环境用户使用命令编译。
6.创建配置文件。该文件可以向模型中传递参数。
7.运行tictoc进行仿真
8.选定仿真的网络实例名为tictoc1,进入界面后,单击工具条中RUN按钮开始仿真。
主窗口的工具栏显示的是仿真时间,这是个虚拟时间,和程序运行的真实时间(你家墙钟记录下的)没有任何关系。事实上,这里显示的仿真时间所对应的物理世界时间的多少更多依赖于你的硬件条件,而不是仿真模型本身的性质和复杂度。提示到在这里的节点本地处理消息时间为零仿真时间,该模型中,仅仅只有链路传播延迟能产生仿真时间。
9. 在仿真图形窗口的顶部(右上角),有一个滑动按钮,你可以通过它来控制仿真速度;按F8 停止仿真(相当于按下工具栏的STOP 按钮),F4 是单步执行模式,F5 是连续带动画模式,F6 是连续无动画模式,F7 是极速模式,完全关闭跟踪特性来追求最大速度。注意到状态栏上的event/sec 和simsec/sec 的量度不同(译者注:event/sec 是每秒处理的事件数,而simsec/sec 是每秒所经历的仿真时间秒数,在本例中,每100ms 产生一个事件,故前者刚好是后者的10 倍)。
10. 点击关闭图标或者选择”File” -> “Exit”来退出仿真程序。
二、 改进型的两节点tictoc
1:增强图形显示,添加调试输出
在这里,我们将做一些工作使得模型在GUI 界面里更好看一些,选择”images/block”目录下的 文件作为tic和toc的图标,分别涂上青色和黄色。这个工作通过在NED文件里增加显示代码行。”i=block/routing”代码行指示了图标文件所在的位置。
2. 增加状态变量
本小节中,我们向模块添加一个计数器,并在十次的消息交换后删除消息。
把计数器作为一个类的成员:
初始化变量为10,并且在经过一次的handleMessage()处理后减1,当它变为0
后,仿真
程序完成所有的事件处理并终止运行。
3. 增加参数
本小节里,你将会学会如何在仿真里添加输入参数:我们将把“神奇的数字”10 作为一个参数并增加一个布尔参数来决定模块是否应该在初始化代码时发送它的第一条消息。(不管它是一个tic 还是toc 模块)。需要在NED 文件里声明模块参数,数据类型可以是数字、字符串、布尔型或者xml。现在,我们可以在NED
文件或者 文件里对参数进行赋值,前者优先于后者。你也可以在NED
文件里使用default(…)给参数定义一个默认值。在这种情况下,你既可以在 里设置参数值,也可以使用NED 文件提供的默认值。
4. 使用继承
如果我们认真查看一下NED 文件就会发现其实tic 和toc 仅仅是在参数值和显示语句上不同而已。我们可以通过从一个简单模块类型继承并修改它的一些参数来得到新的简单模块类型。在本例中,我们得到了两个简单模块类型(tic 和toc)。只要在网络中定义之后,接下来我们就可以使用这些类型了。
5. 建立延迟处理模型
在之前的模型里,tic 和toc 收到消息后都立即回传,没有处理延迟。接下来我们将给节点增加1 个仿真秒的处理延迟,然后再回传。在OMNeT++里,通过模块给自身发送消息来这种计时。这种消息也被称之为“自消息”。(不同的只是这种消息的使用方式,不然它们也只是普通的消息对象)我们在类里增加两个cMessage 指针变量:event和tictocMsg,分别用来指向我们用来计时的事件消息和我们要进行仿真其延迟处理的数据包消息。
6. 随机数和参数
本小节我们将介绍随机数。把之前的延迟设为1s 到一个随机数之间,该随机数可以在NED 文件或者 文件里设置。模块参数也可以返回随机数变量,但是,要想使用这个功能,我们不得不在每次调用handleMessage()函数的时候去读那个参数。
7.超时和时钟中止
为了更进一步地模拟网络协议,我们把之前的模型改成一个“停-等”仿真,这次将把tic 和toc 的类区分开来,基本场景还是和之前类似:tic 和toc 彼此来回传递消息。但是,在非零概率下,toc 将会发生丢包,这个时候我们需要重传数据包。
所以,当tic发送消息的时候,它就启动一个计时器,一旦计时器届满,就认定消息丢失了,然后重新再发一份。如果收到toc的回复包,计时器就会被取消。
8. 消息重传
在本小节理我们对之前的模型进行进一步优化。之前在需要重传时我们就重新创建另一个数据包,当数据包比较小的时候这个是没有问题的,但在实际生活中,通常采取的措施是保留一份源拷贝,这样在重传的时候就不需要重新创建数据包。我们在这里采取的是保留原始数据包,而把拷贝副本发送出去,当toc 的应答包到来的时候,我们才删除原始包。为了便于直观地检验该模型,我们在每个消息上增加了一个消息序列号。
9. 两个以上节点组成的网络
现在我们来进行一次比较大的跨越:创建几个tic 模块并把它们连成一个网络。它们所做的事情很简单:其中一个节点产生一个消息,其他节点随机传送该消息,直到它到达预先指定的目标节点。相应的NED 文件需要做一些修改,首先,Txc 模块必须包含多个input 和output 门:方括号[]把之前的门变成了门向量,当我们用Txc 来建立网络的时候,才决定其向量的大小(门数)。在这里我们创建了一个模块向量,包含6 个模块,模块连接后的拓扑如下:
在这个版本里,tic[0]将产生消息并发送给周围节点,这个是在调用初始化函数initialize()完成的,初始化函数调用getIndex()函数,该函数返回该模块在向量中
的索引。当一个消息到达节点的时候,handleMessage()函数就会调用fowwaredMessage(),获取一个随机的的门编号(编号在门向量范围内),然后从该门发送出消息。当消息到达tic[3]时,它的handleMessage()函数将会删除这个消息。
10. 信道和内部类型定义
我们刚才定义的网络显得太过复杂和冗长,特别是连接部分。让我们试着来简化一下。首先我们注意到基本上所有的连接都使用相同的延迟参数,可以给这些相似的连接(信道)创建类型。我们可以创建一个信道类型来指定延迟参数,然后在网络中的所有连接上使用这种类型。
11. 使用双向连接
如果我们更仔细地检查刚才的连接部分,我们可以发现每个节点对通过两个连接连在一起,每个方向各一个连接,OMNeT++提供了双向连接,我们可以使用它。首先,我们需要定义一个双向门(inout)来取代之前的input 和output 门。
12. 自定义我们的消息类
本小节里,目标地址不再是指定的tic[3],我们将使用一个随机的目标地址并让消息带上该地址。最好的方法是派生cMessage 子类并添加一个数据成员。手动编码消息类通常会很冗长,因为包含很多的样板代码(boilerplate code),所以我们让OMNeT++为我们创建这个类。
三、 增加统计收集
13. 显示消息收发数目
通过给模块类加入两个计数器:numSent 和numReceived,就可以在运行时记录下每个节点收发的消息数。在离散仿真模型中,各节点的收发数目大致相同,这说明均匀分布函数intuniform()工作正常。但是在现实仿真中你可以快速了解模型中各节点的状态,这点很有用。
14.我们可以统计仿真中的感兴趣变量。
我们将记录每条消息的跳数,并记录为向量对数据输出。然后我们按节点统计出均值、标准差、最小值及最大值。仿真结束时将这些值保存到文件中,以便用离线工具分析。
四、 通过Plove和Scalars 可视化结果
1. 标量、向量输出可视化
OMNeT++ IDE 可以帮你分析结果数据。它可以过滤、处理和显示向量及标量数据,当然也可以显示柱状图。下面的图表就是IDE 的结果分析工具所创建
的。
上一次的模型中记录了一个消息每次到达目标节点所经历的跳数,下图显示了节点0 和节点1 的这些向量结果:
如果我们应用一个求均值的操作,就可看到不同节点的跳数如何趋向一个平均值:
下图显示了到达每个目标节点的消息所经历平均跳数和最大跳数,基于仿真结束后所记录的标量数据:
下图显示了跳数分布的柱状图:
2. 顺序图
OMNeT 仿真内核可以把仿真期间的消息交换历史记录到一个日志文件。该文件稍后可以用顺序图工具(Sequence Chart tool)进行分析。
下图是通过顺序图工具创建的,显示了消息在网络中两个不同节点之间是如何被路由转发的。这个例子中的图标非常简单,但是当你的模型很复杂的时候,顺序图在进行调试(debugging)、探测(exploring)和记录(documenting)模型行为的时候非常有价值。
版权声明:本文标题:基于OMNET++的tictoc仿真实验报告 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1708852066h532644.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论