OMNET++工具的使用(2)
http://blog.csdn.net/codingkid/article/details/7085214
首先解决一些概念上的问题:
1. 在omnetpp.org中提到的仿真模型和框架与OMNet++是什么关系?
OMNet++提供了基本的工具和机制来编写仿真代码,但它本身并不提供任何特定用于计算机网络仿真,系统架构仿真和任意其它领域的组件;具体的仿真是由一些仿真模型和框架如Mobility Framework或INET Framework来支持,这些模型独立于OMNet++开发,并有自己的发布周期。
2. OMNet++提供了什么?
一个C++库,它由仿真内核及一些用来创建仿真组件(简单模块和信息)的工具类(如随机数生成,统计收集,拓扑发现等);组装和配置这些组件的基础设施(NED语言,ini文件);运行时用户接口或仿真环境(TKenv,Cmdenv);一个用来设计,运行和评估仿真的IDE环境;实时仿真的扩展接口;MRIP,并行的分布式仿真,数据库连接等等这些组成。
3. OMNet++的仿真模型是什么样的?
OMNet++提供了一个基于组件的架构,模型是由可重用的组件或模块组成的。模块之间可以通过gates(在其它系统中称为ports,即端口)进行连接,以构成复合模块。每个仿真模型是一个复合模块类型的实例。这一层次(组件和拓扑)由NED文件来处理。
NED文件只定义了模型的结构(拓扑),其行为和模块参数的某个子集则是开放的,如前面所提到的,行为是通过在简单模块相关联的C++代码来定义的,而在NED文件中没有赋值的模块参数则从ini文件中获取它们的值。
5. 仿真的输出是什么?
仿真过程中会有向量输出和标题输出,默认文件名为omnetpp.vec和omnetpp.sca,尽管omnetpp.ini可以指定输出为不同的文件名,仍需要在简单模块中进行编码以让其拥有记录仿真结果的能力,所以在他人编写的仿真中可能并不创建这些文件。
一个输出向量文件包含若干输出向量,每一个向量都是一个 (timestamp,value) 对。输出向量可以存储例如关于时间的队列长度,接收数据包时端到端的延迟,丢弃的数据包或者信道吞吐量—任意在简单模块中的编程所定义的统计量都可以。并且,可以在omnetpp.ini中配置输出向量:即可以启用或者关闭记录某个输出向量,或者用一定的仿真时间间隔来进行限制。可以通过查看cOutVector对象的C++的源代码来查看一个简单模块可以获取的输出向量。
输出向量根据时间来捕获行为,而输出标量文件则包含总的统计量:发送包的数目,丢弃包的数目,平均的端到端延迟,吞吐量的峰值等。可以在recodScala() 方法的调用 ,特别是在一个简单模块类中的finish()方法中查看输出标量。
输出向量可以用Plove程序来绘图,而输出标量则可以使用Scalars程序来绘图。
6. 关于随机数
OMNeT++默认的随机数生成器是 Mersenne Twister,种子可以自动获取,或者在omnetpp.ini中定义。OMNeT++ 支持很多种概率分布,并且在NED和C++中都是可用的(在 3.2 版本中有 14 个连续的分布和 6 个离散的分布, 具体可以查看 API doc)。非常量的模块参数可以用随机变量来赋值,如 exponential(0.2), 它表示C++代码会在每次读取参数时获得一个不同的数字;这是指定随机流量源的一种很方便的方法。( 常量参数也能用表达式如exponential(0.2)来赋值,但它只会被计算一次并且不再改变)。
7. 是否可以在OMNeT++中进行MRIP,分布式并行仿真,网络模拟,或feature X?
可以。OMNet++ 具有很强的可扩展性并且开放源代码,一些特性是可以开箱即用的:
MRIP是指 multiple replications in parallel,而Akaroa是一个很出色的工具。你可以单独地下载并安装它,然后启用OMNet++的Akaroa支持进行重新编译,但AFAIK Akaroa仅可以在 Linux(*nix)中使用,在OMNeT++的手册中可以找到更多信息。
如果仿真需要大量的内存,则可以在集群中运行仿真。分块和其它配置可以在omnetpp.ini中定义,但仿真模型本身却不用进行改变(除非模型包含全局变量可能导致不能分布地运行)。通信层使用的是MPI,但事实上这是可配置的,所以如果你没有MPI的话也仍然可以通过命名管道,或者基于文件的信息交换来进行一些基本的测试。当然如果需要,你也可以通过实现abstract cParsimCommunications接口来添加一个新的方案。
网络模拟,实时仿真和类似于hardware-in-the-loop的功能是可用的,这是因为在仿真内核中的事件调度器是可插拔的。OMNet++的一个Demo展示了如何进行实时仿真和一个简单的网络模拟的样例,足以让你进入这个领域。Real network emulation with the INET Framework is in the queue.
可以用一个数据库来代替omnetpp.ini文件作为配置数据的源,也能将仿真结果重定向到数据库中,OMNeT++ 中包含这样一个Demo,可以作为参考。
由于你拥有全部的源代码和良好的文档,所以你能根据自己的想法来实现很多事情。
8. 如何在C++代码中编写模型?
简单模块其实是C++类,你从cSimpleModule继承子类,重定义一个虚成员函数,并通过Define_Module()宏来将新的类注册到OMNeT++中。
模块间主要使用消息传递进行通讯,而timers(timeouts)也处理模块发送给自身的消息。消息应当是cMessage类或者是其子类,消息将被传递到模块的 handleMessage(cMessage *msg) 方法,在这里应当添加你的代码。几乎你想定义的模块行为都在handleMessage() 之中定义,因此这段代码块可能会很长,所以将其重构为其它成员函数例如命名为processTimer(),processPacket()是一个好主意(可以将activity() 方法视为handleMessage()的一个替换,但是在实践中最好不要这么做。)。
你可以使用send(cMessage *msg, const char *outGateName) 方法来向其它模块传递消息,对于无线仿真和一些情况下,则可以更方便地直接传递消息到其它模块而不用在NED文件中建立连接。这可以由sendDirect(cMessage *msg, double delay, cModule *targetModule, const char *inGateName)方法来完成。Self-messages (that is, timers can be scheduled) 可以通过scheduleAt(simtime_t time, cMessage *msg) 进行传送,并且在它们失效前可以通过cancelEvent(cMessage *msg) 来取消。这些函数都是cSimpleModule类的成员,在文档中可以找到更多的相关信息。
基本的cMessage类包含几个数据成员,最重要也最实用的是name,length,message”kind”(一个int成员)。其它数据成员则存储此消息最近发送/调度的信息:arrival time,arrival gate等。为了进行协议仿真,cMessage可以封装另外一个cMessage对象,可以查看它的encapsulate(cMessage *msg) 方法进行了解。这些方法也能逐步地修改域的长度。如果你需要在消息中运送更多的数据,其它数据成员可以通过继承来添加。然而,你并不需要手工编写新的C++类,可以更方便地在一个.msg文件中定义,从而让OMNet++( opp_msgc 工具) 来为你生成C++类。生成的C++文件会拥有_m.h,m.cc的后缀。.msg文件支持进一步的继承,组合,数组成员等等,并且它拥有可以让在C++类中自定义的语法。一个消息文件的例子如下:
1 |
message NetworkPacket { |
2 |
fields: |
3 |
int srcAddr; |
4 |
int destAddr; |
5 |
} |
OMNet++经常用来进行网络协议的仿真,cMessage有一个叫control info的域,它包含额外的信息来促进协议层间的通讯。例如,当应用层发送数据(一个消息对象)到TCP来传输时,它能在包含socket标志符的信息中附加一小段控制信息(一个对象)。或者,当TCP发送一个TCP segment到IP层传输时,它附加包含目标IP地址的控制信息,也可能是其它的一些选项,如TTL。控制信息也能发送到其它方向(向上),以便向上一层标记源IP地址或者TCP连接。控制信息是通过cMessage的 setControlInfo(cPolymorpic *ctrl) 和 removeControlInfo() 方法来处理的。
其它cSimpleModule模块中需要重定义的虚成员函数是initialize()( 主要的初始化工作在这里进行,因为在构造函数的调用过程中模型也正在构建),initialize(int stage) 和多阶段初始化的int numinitStages() const(这在一个模块的初始化代码依赖于其它已经初始化完毕的模块时很有用),finish()来记录总的结果(析构函数不适宜用于这种用途)。如果你想要模块感知参数(参数可以交互式地在GUI中或由其它模块改变,因此你需要重新读取这个参数)在运行时的改变,则需要重定义handleParameterChange(const char *paramName)方法。
简单模块的NED参数可以使用par(const char *paramName) 方法来读取,在典型的情况下,这个过程会在initialize()中进行,并将这些值存储在模块类的数据成员中。par()返回一个cPar对象的引用,这个引用可以用C++的语法或调用对象的doubleValue()方法等这些途径转为合适的类型(long,double,const char*,etc)。除了基本的类型,也可以是XML文件:参数可以赋值到XML文件中,它能用以DOM的对象树的形式向C++代码展示。
消息传递并不总是模块间通讯的最好方法。例如,如果你设计了一个用于收集统计的模块(常使用全局变量),通过消息来传递统计量的更新,不如将统计模块作为一个C++对象,并调用它的用于此目的的公共成员函数(如updateStatistics(…))来得简便。
对方法的直接调用有一些技术细节。首先你需要查找其它模块:cModule的parentModule() 和submodule(const char*name)方法可以查找到与当前相关的模块,而simulation.moduleByPath(const char *path) 可以通过一个绝对的路径名在全局查找一个模块,一旦你拥有其它模块的指针,你需要将它转化为实际的类型(i.e. to StatisticsCollector* from cModule*),这是由拥有与C++的dynamic_cast相同语法的check_and_cast来完成,但如果转换不成功或指针为NULL时它会抛出一个错误。public的方法应当将Enther_Method()或者Enter_Method_Silent(…) 放置在顶端,它们启用了GUI的动画调用,同时进行了一些与临时上下文切换相近的行为(在这里并不深究,但如果想要在方法中进行消息处理这是必须的)。INET框架广泛地使用了方法调用来访问模块,如RoutingTable, InterfaceTable, NotificationBoard等。
INET的NotificationBoard在一些仿真中很有用,它通过对信息的产生者和消费者进行解耦,在它们之间转发变化的notifications或者事件的notifications,从而支持几个模块间的信息共享(NotificationBoard宽泛地基于blackboard 区域,但在实践中,仅转发notifications比存储blackboard中发布的信息更简单有效。进一步地,notifications可能包含实际的数据或者指向数据的指针的拷贝)。
对于调试,模块中打印一些必要的信息是很关键的。在OMNet++中使用ev<< (类似于printf和cout)将输出写到可以进行过滤的GUI窗口中,同时模块用图标的颜色或文件标签及tooltips来展示状态也有助于减少调试的时间;这个可以通过在执行时改变display string来完成(查看cModule's displayString())。通过调用bubble(const char*text)方法,可以在模块的上方看到一个短暂出现的“气泡”或“气球”,这也是很有帮助的。另外一种调试的辅助是WATCH(variableName) 宏及其变种 (WATCH_VECTOR, 等),它能让你在Tkenv GUI中查看变量的值(you'll find watched variables in the "Contents" tab of the module's inspector)。
为了记录输出向量,你应当添加一个cOutVector对象到类中作为一个数据成员(或者用new来创建),设置name string作为输出向量的名字,然后持续调用它的record(double value)方法来记录数字。输出标量最好编写在模块(请查看cModule中的 recordScalar(const char *name, double value) 方法)的finish() 函数中,可以基于计数器作为模块的数据成员。也可以计算基本的统计和图表:请参考cStdDev, cDoubleHistogram and cLongHistogram classes 这些类。
NED文件描述静态的拓扑,但也能动态地创建模块和连接。这在网络拓扑不是以NED文件(如普通文本文件,Excel sheet,database等)存储,或者你想在运行时动态地创建和删除模块的情况下很有用。在前一种情况下,一般可以通过Awk,Perl,Python,Ruby,TCL或在文本编辑中一系列的查找/匹配操作来将数据转化为NED。然而,当你决定以C++来创建动态模块时,对一个样本NED文件调用nedtool并查看生成的_n.cc文件会很有帮助。
接着动手编写一个工程来运行:
可以参照这篇文章http://leeing.org/2010/01/24/the-ned-language-of-omnetpp-4-0/
OMNET++工具的使用(2)的更多相关文章
- Omnet++ 4.0 入门实例教程
http://blog.sina.com.cn/s/blog_8a2bb17d01018npf.html 在网上找到的一个讲解omnet++的实例, 是4.0下面实现的. 我在4.2上试了试,可以用. ...
- OMnet++ 初学者教程 第一节 入门
第1部分-入门 1.1模型 首先,让我们从一个包含两个节点的"network"开始.节点将做一些简单的事情:一个是节点将创建一个数据包,而两个节点将继续来回传递相同的数据包.我们将 ...
- omnet++:官方文档翻译总结(五)
Part 6 - 用IDE将结果可视化 学习翻译自:Visualizing the Results - OMNeT++ Technical Articles ①将输出的数值和向量数据可视化(用tict ...
- omnet++:官方文档翻译总结(四)
学习翻译自:Adding Statistics Collection - OMNeT++ Technical Articles Part 5 - Adding Statistics Collectio ...
- omnet++:官方文档翻译总结(一)
1.什么是omnet++ 翻译总结自:What is OMNeT++? omnet++是用来进行网络仿真的C++库和框架.这里的网络包括有线.无线.on-chip.queueing网络等等.特定领域中 ...
- omnet++:官方文档翻译总结(二)
这一部分是官方案例介绍 1.Introduction 学习自:Introduction - OMNeT++ Technical Articles 本教程是基于Tictoc的仿真案例,这些案例我们可以在 ...
- omnet++:使用教程
学习自:(6条消息) omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_叶局长的博客-CSDN博客 1.使用omnet仿真的一般步骤 主要有3步: 使用ned(network ...
- Unity3d入门 - 关于unity工具的熟悉
上周由于工作内容较多,花在unity上学习的时间不多,但总归还是学习了一些东西,内容如下: .1 根据相关的教程在mac上安装了unity. .2 学习了unity的主要的工具分布和对应工具的相关的功 ...
- 细说前端自动化打包工具--webpack
背景 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过链接组织在一起.用过Dreamweaver的都知道,做网页就像用word编辑文档 ...
随机推荐
- java中的单引号和双引号
1.单引号引的数据 是char类型的,双引号引的数据 是String类型的:单引号只能引一个字符,而双引号可以引0个及其以上.char只是一个基本类型,而String 可以是一个类,可以直接引用.比如 ...
- Intellij IDEA 快捷键(Mac)
编辑 格式化代码 Alt+Command+L 大小写切换 Shift+Command+U 包围 Alt+Command+T 选中代码抽取方法 Alt+Command+M 调试/运行 查看 类关系视图 ...
- 24Mybatis_延迟加载——用association来实现
resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 需求: 如果查询订单并且关 ...
- 快捷键forMac
1.手动补全快捷键 设置completion+basic或者completion+smartType 2.快速导入指定API的包 command+1
- 不支持一个 STA 线程上针对多个句柄的 WaitAll
[csharp] view plaincopy using System; using System.Collections.Generic; using System.Windows.Forms; ...
- MySQL数据备份小结
一 MySQL备份恢复总结: 1,备份所有库 2,分库备份 3,备份某库中的某表 4,备份某库中的多个表 5,分表备份 6,只备份表结构 7,只备份数据 二 MySQL备份恢复参数总结: -A 备份所 ...
- JS 模板引擎之JST模板
项目中有用到JST模板引擎,于是抽个时间出来,整理了下关于JST模板引擎的相关内容. 试想一个场景,当点击页面上列表的翻页按钮后,通过异步请求获得下一页的列表数据并在页面上显示出来.传统的JS做法是编 ...
- 修改TrustedInstaller权限文件(无法删除文件)
1. 右击需要修改的文件-属性 2. 切换到"安全"选项卡,点击"高级"按钮. 3. 切换到"所有者"选项卡 一般情况下默 ...
- Android--图片集
一. 实现效果 安卓系统中的相册集效果图,左右滑动可以查看上一张或者下一张图片 二. 布局代码 <?xml version="1.0" encoding=" ...
- jquery基本方法
jquery的delay sleep 与js的setTime的区别. delay 和sleep推荐不要用,太难用了. click on live delegate bind http://www.jb ...