第二章 OMNeT++ TicToc 教程
概述
这是一个简短的教程,通过一个建模和仿真的实例来引导你入门,同时向你介绍一些广
泛使用的 OMNET++特性。
本 教 程 基 于 一 个 简 单 的 Tictoc 仿 真 样 例 , 该 样 例 保 存 在 OMNET++ 安 装 目 录 下 的
samples/tictoc 子目录,所以你现在可以试着让这个样例运行,运行样例有两种方式:
一是直接在 mingwenv 下 cd 到 samples/tictoc,输入./tictoc 即可;
另一种是在 mingwenv 下输入 omnetpp 进入 IDE,在左侧的 Project Explorer 窗口下显示了
samples 目录下的工程样例(如果没有,则通过 File—>Switch Workspace—>Other 来切换工
作空间,注意每次切换 Workspace 将使 IDE 重启),找到 tictoc 案例,右键依次选择 Open
Project,Build Project,Run As—>Run Configurations,在窗口左侧 new 一个 omnet++ simulation,
右侧 Name 为 tictoc,Options 的 User interface 选 Commamd line,Record Eventlog 选 Yes 之后点
击 Run,最后右键 Run As|Run Simulation 即可运行。
为了使读者更容易学习此样例,这里所有的源代码都交叉链接到 OMNET++API 文档。
如果你跟着以下的步骤一步一步走,你将会收获很大。
目录
1. 入门
2. 改进型的两节点 TicToc
3. 模拟真实网络
4. 增加统计收集
5. 通过 Plove 和 Scalars 进行结果可视化
2.1 入门: Tictoc1:两个简单节点
由于 OMNeT++最常见的应用领域是电信网络的仿真,我们就从这开始我们的主题。首先,
让我们来考虑一个包含两个节点的“网络”,节点所做的事情非常简单就是:一个节点创建
数据包,然后这两个节点将该数据包来回传送,我们把这两个节点分别称之为“tic”和“toc”。
从零开始——实现你的第一个仿真的步骤:
我们建议在 IDE 下开始:
首先,开发环境选择 simulation 的视图,这是 Omnet++ 开发的最优环境,在这个视
图 下 有 好 多 针 对 Omnet++ 的 专 有 菜 单 项 。 打 开 过 程 : Windows->open
perspective->simulation。
新建一个 Omnet 的工程,取名为 astictoc (以防与样例在同一工作空间,不允许重名):
File->New->Omnet++ Project。
接着我们要为我们的网络编写一个 NED 文件来描述该样例网络。拓扑文件是标识网络
节 点 及 其 链 路 的 文 本 文 件 , NED 语 言 主 要 是 用 来 描 述 仿 真 模 型 结 构 右 键 点 击
astictoc->New->Netw Descripition File ,新建一个 NED 文件,命名为 tictoc1.ned , content
选 A new network 我们对它取名为 tictoc1.ned,有两种编辑方式,可视化以及代码方式,我
们在这里利用代码方式:
//
// This file is part of an OMNeT++/OMNEST simulation example.
//
// Copyright (C) 2003 Ahmet Sekercioglu
// Copyright (C) 2003-2008 Andras Varga
//
// This file is distributed WITHOUT ANY WARRANTY. See the file
// `license' for details on this and other legal matters.
//
simple Txc1
{
gates:
input in;
output out;
}
//
// Txc1 的两个实例 tic 和 toc 相互链接
//tic 和 toc 将相互传送消息
//
network Tictoc1
{
submodules:
tic: Txc1;
toc: Txc1;
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
}
最好从下往上看,意思如下:
Tictoc1 是一个包含两个子模块的网络,tic 和 toc。
这两个模块都是一个称做 Txc1 的简单模块类型的实例。我们把 tic 的输出门(out)
连到 toc 的输入门(in),反过来也一样( network … {…} )。每个链路上会有 100ms 的
传播延迟。
Txc1 是一个简单模块类型(这意味着是 NED 描述
的一个基本单位,在 NED 层上是具有原子性的,并通过 C++实现)。Txc1 有一个叫
做 in 的输入门和一个叫做 out 的输出门。(simple … {…} )。
3. 现在我们需要实现简单模块 Txc1 的功能,通过写一个 C++文件(txc1.cc)来完成。右键
点击 astictoc->New->File,新建一个文件,命名为 txc1.cc:
//
// This file is part of an OMNeT++/OMNEST simulation example.
//
// Copyright (C) 2003 Ahmet Sekercioglu
// Copyright (C) 2003-2008 Andras Varga
// This file is distributed WITHOUT ANY WARRANTY. See the file
// `license' for details on this and other legal matters.
//
#include
#include
class Txc1 : public cSimpleModule
{
protected:
// 以下重新定义的虚函数带有算法.
virtual void initialize();
virtual void handleMessage(cMessage *msg);
};
// 该模块类需要向 omnet++注册
Define_Module(Txc1);
void Txc1::initialize()
{
// Initialize 在仿真的开始被调用.
// 为了引导 tic-toc-tic-toc 过程, 其中的一个模块需要先发送一个消息,设置 tic 先发送.
// 判断我是 tic 还是 toc
if (strcmp("tic", getName()) == 0)
{
// 在输出门产生并发送第一个消息, "tictocMsg" 是一个任意的字符串代表消息对象的名字
cMessage *msg = new cMessage("tictocMsg");
send(msg, "out");
}
}
void Txc1::handleMessage(cMessage *msg)
{
// 当消息到达模块的时候 handleMessage()方法被调用,在此,我们仅仅把消息通过输出门发送
//到另一个模块,由于 tic 和 toc 对消息的处理相同,所以信息就在两个模块之间不停地反弹。
send(msg, "out");
}
名为 Txc1 的 C++类描述了 Txc1 简单模块类型,该类是 cSimpleModule 的一个子类,并
通过 Define_Module()宏向 OMNeT++注册。我们对其中的 initialize()和 handleMessage()函数进
行重载。这两个函数将被仿真内核调用:其中初始化函数 initialize()只会被调用一次,而
handleMessage()则在每次消息到达模块时被调用。
在初始化函数中我们创建了一个消息对象(cMessage)并通过输出门 out 对外发送。因为
该门连接到其他模块的输入门,所以仿真内核将会把 handleMessage()函数参数中携带的这
个消息传递给其他模块。该消息将会在 NED 文件中指派给链路的 100ms 传播延迟后到达。
其他模块收到后同样将该消息送回(仍然经过 100ms 的延迟),所以整个过程就像一个永不停
歇的乒乓球一样。
在 OMNeT++中,所有的消息(数据包、帧、任务等)和事件(定时、超时)都通过 cMessage
对象(或它的子类)描述。一旦它们被送出或者被调度,就会被仿真内核放在”已调度事件”和”
未来事件”列表中,直到时钟来临,再通过 handleMessage()传递到相关模块。
要注意到在本仿真样例中,并没有内建停止条件,也就是说,仿真会一直进行下去。
你可以从 GUI 图形界面停止它。(你也可以在配置文件里指定一个仿真时间限制或者 CPU 时
间限制,但在本教程里我们并没有这样做)。
4. 现在我们来创建一个 Makefile 来帮助我们对程序进行编译和链接,并创建一个可执
行的 tictoc:在 mingwenv 下 cd 到 astictoc 目录,输入
$ opp_makemake
这条命令将会在 astictoc 工作目录下产生一个 Makefile 文件。
注意:对于 Windows+MSVC 的用户,命令是 opp_nmakemake,它将创建 Makefile.vc。
5.现在我们来编译和链接我们的第一个仿真实例,运行如下命令:
$ make
注意:对于 Windows+MSVC 的用户,键入 nmake –f Makefile.vc。如果提示说 nmake 命令
既非内部命令也非外部命令…,那你需要在 MSVC 目录下找到 vcvars32.bat,然后在你想要编
译的每个命令窗口运行它。//sunfast
6. 如果你现在就运行编译之后产生的可执行程序,将会提示找不到 omnetpp.ini 配置文
件,所以你需要手动建立一个。omnetpp.ini 将告诉仿真程序你想要仿真何种网络(同个仿真
程序可以支持同时仿真几种网络//sunfast),你可以将参数传递给模块、显式指定随机数产生
器的种子等。
右键点击 astictoc 新建一个 omnetpp.ini 文件,选择 Network 为 astictoc ,finish。在
这里,我们同样选择代码方式创建如下简单的 omnetpp.ini 文件:
[General]
network = tictoc1
在 tictoc2 及其之后的步骤里,omnetpp.ini 的文件都是这样的:
# This file is shared by all tictoc simulations.
# Lines beginning with `#' are comments
[General]
# nothing here
[Config Tictoc1]
network = Tictoc1
[Config Tictoc2]
network = Tictoc2
[Config Tictoc3]
network = Tictoc3
[Config Tictoc4]
network = Tictoc4
Tictoc4.toc.limit = 5
[Config Tictoc5]
network = Tictoc5
**.limit = 5
[Config Tictoc6]
network = Tictoc6
[Config Tictoc7]
network = Tictoc7
# argument to exponential() is the mean; truncnormal() returns values from
# the normal distribution truncated to nonnegative values
Tictoc7.tic.delayTime = exponential(3s)
Tictoc7.toc.delayTime = truncnormal(3s,1s)
[Config Tictoc8]
network = Tictoc8
[Config Tictoc9]
network = Tictoc9
[Config Tictoc10]
network = Tictoc10
[Config Tictoc11]
network = Tictoc11
[Config Tictoc12]
network = Tictoc12
[Config Tictoc13]
network = Tictoc13
[Config Tictoc14]
network = Tictoc14
[Config Tictoc15]
network = Tictoc15
record-eventlog = true
7. 一旦你完成了上述步骤,你可以通过执行如下命令来运行仿真:
$ ./tictoc
不出意外的话,你就可以见到 OMNeT++仿真窗口了。
8. 点击工具栏的“运行”按钮就可以开始仿真,你将看到 tic 和 toc 彼此之间在相互交
换消息。
注意观察 Tkevn:** Event #1 T=0.1 Tictoc1.toc (Txc1, id=3), on `tictocMsg' (cMessage, id=6),
可能有人会不理解,为什么第一个消息是 toc 发的?在运行之前,让我们点击 Tkenv 左边窗
口中的 sheduled-event,弹出的窗口如下:
从中我们可以看到 src 为 tic,dest 为 toc,消息的 creation Time=0,sending Time=0,由 NED 文
件知道 delay 时间为 100ms,即到达时间 arrivalTime=0.1s,由此可知 Tkenv 中的 Event #1 指的
是 toc 在 0.1s 的时候持有该信息,而不是发送信息。
主窗口的工具栏显示的是仿真时间,这是个虚拟时间,和程序运行的真实时间(你家墙钟
记录下的)没有任何关系。事实上,这里显示的仿真时间所对应的物理世界时间的多少更多
依赖于你的硬件条件,而不是仿真模型本身的性质和复杂度。
注意到在这里的节点本地处理消息时间为零仿真时间,该模型中,仅仅只有链路传播延
迟能产生仿真时间。
9. 在仿真图形窗口的顶部(右上角),有一个滑动按钮,你可以通过它来控制仿真速度;
按 F8 停止仿真(相当于按下工具栏的 STOP 按钮),F4 是单步执行模式,F5 是连续带动画模
式,F6 是连续无动画模式,F7 是极速模式,完全关闭跟踪特性来追求最大速度。注意到状
态栏上的 event/sec 和 simsec/sec 的量度不同(译者注:event/sec 是每秒处理的事件数,而
simsec/sec 是每秒所经历的仿真时间秒数,在本例中,每 100ms 产生一个事件,故前者刚好
是后者的 10 倍)。
10. 点击关闭图标或者选择”File” -> “Exit”来退出仿真程序。
源文件: tictoc1.ned, txc1.cc, omnetpp.ini(也可以在 tictoc 样例下打开.ned,.cc,.ini 文
件查看源码)。
2.2 改进型的两节点 TicToc
2.2.1 Tictoc2: 完善图形, 并增加调试输出
在这里我们美化一下图形用户界面中的模型,我们指定"block/routing" 图标 (文件
images/block/routing.png), 为 tic 添加青绿色,为 toc 添加黄色,这是通过在.ned
文件中添加 display 字符串达到的。diaplay 字符串中的 i=tag 指定图标。
// "block/routing" icon to the simple module. All submodules of type
// Txc2 will use this icon by default
//
simple Txc2
{
parameters:
@display("i=block/routing"); // 添加一个默认图标
gates:
input in;
output out;
}
// 使两个图标的着色看起来不一样
// `tic’青绿色,`toc'黄色
network Tictoc2
{
submodules:
tic: Txc2 {
parameters:
@display("i=,cyan"); // do not change the icon (first arg
of i=) just colorize it
}
toc: Txc2 {
parameters:
@display("i=,gold"); // here too
}
connections:
你可以看到如下结果: