通过Omnet++官网tictoc教程学习在Omnet++中构建和运行仿真 Part1&Part2

Omnet++官网 TicToc教学

introduce

在 Omnet++安装完成后,samples/tictoc 中有该例子的完整文件,你可以立刻运行该文件看他是怎么工作的,不过更推荐按接下来的步骤一步步完成该项目的构建。
在这里插入图片描述
需求:

  1. 安装好了Omnet++
  2. 拥有良好的C++知识、C++开发经验
  3. To make the examples easier to follow, all source code in here is cross-linked to the OMNeT++ API documentation.

开始

模型介绍

创建一个有两个节点的网络,其中一个节点会创建一个数据包,两个节点会来回传递相同的数据包,这两个节点分别叫做 tic和toc ,接着我们会逐渐拓展这个模型,在这个过程中介绍Omnet++的特征。

构建项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果有一些版本生成了 package.ned 文件,要将其删除

本项目所有文件都包含在一个文件夹中,对于一些更大规模的文件,可能会创建多个子文件夹。

添加 NED 文件

OMNeT++ 使用 NED 文件来定义组件并将它们组装成更大的单元 就像网络一样。
创建名为 tictoc1.ned的ned文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建后,可以在 OMNeT++ IDE 的 “Editor”(编辑器)区域中编辑该文件。 OMNeT++ IDE 的 NED 编辑器有两种模式:Design 和 Source; 在它们之间使用编辑器底部的选项卡可以进行切换。在“设计”模式下, 可以使用鼠标和右侧的调色板以图形方式编辑拓扑。 在源模式下,NED源码可以直接编辑为文本。 在一种模式下完成的更改将立即反映在另一种模式中,因此您可以 在编辑过程中自由切换模式,并在任何模式下进行更改。
在这里插入图片描述
选择Source模式,将如下代码输入进去:

simple Txc1
{
    gates:
        input in;
        output out;
}

//
// Two instances (tic and toc) of Txc1 connected both ways.
// Tic and toc will pass messages to one another.
//
network Tictoc1
{
    submodules:
        tic: Txc1;
        toc: Txc1;
    connections:
        tic.out --> {  delay = 100ms; } --> toc.in;
        tic.in <-- {  delay = 100ms; } <-- toc.out;
}

再返回到 Design模式,可以看到如下类似的图像
在这里插入图片描述
文件中的第一个块声明 Txc1作为简单的模块类型。 简单模块在NED级别上是原子的。它们也是有源成分, 他们的行为是在 C++ 中实现的。该声明还说,Txc1有一个名为 in 的输入门和一个名为 out 的输出门。

第二个块 Tictoc1 声明为网络。 Tictoc1由两个子模块 tic和 toc 组装而成 ,两者都是模块 Txc1的实例。tic的输出门连接到toc的输入门,反之亦然。 双向传播延迟为 100 毫秒。

注:ned语言更详细的介绍见ned语言 ,在安装完Omnet++后再 doc文件夹下也可以找到这些文档

添加C++ 文件

现在通过添加C++文件来编程Txc1模块的功能,创建一个名为 txc1.cc的文件
在这里插入图片描述

在这里插入图片描述
将如下代码输入到 Txc.cc中

#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;

/**
 * Derive the Txc1 class from cSimpleModule. In the Tictoc1 network,
 * both the `tic' and `toc' modules are Txc1 objects, created by OMNeT++
 * at the beginning of the simulation.
 */
class Txc1 : public cSimpleModule
{
  protected:
    // The following redefined virtual function holds the algorithm.
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

// The module class needs to be registered with OMNeT++
Define_Module(Txc1);

void Txc1::initialize()
{
    // Initialize is called at the beginning of the simulation.
    // To bootstrap the tic-toc-tic-toc process, one of the modules needs
    // to send the first message. Let this be `tic'.

    // Am I Tic or Toc?
    if (strcmp("tic", getName()) == 0) {
        // create and send first message on gate "out". "tictocMsg" is an
        // arbitrary string which will be the name of the message object.
        cMessage *msg = new cMessage("tictocMsg");
        send(msg, "out");
    }
}

void Txc1::handleMessage(cMessage *msg)
{
    // The handleMessage() method is called whenever a message arrives
    // at the module. Here, we just send it to the other module, through
    // gate `out'. Because both `tic' and `toc' does the same, the message
    // will bounce between the two.
    send(msg, "out"); // send out the message
}

类Txc1 代表了基础模块 Txc1 ,Txc1是 Omnet++中 cSimpleModule 的子类,并且使用Define_Module() 函数宏注册到 Omner++中 。

如果忘记使用 Define_Module() 将自己新构建的模块宏注册到 Omnet++中,将会得到如下类似的报错: “Error: Class ‘Txc1’ not found – perhapsits code was not linked in, or the class wasn’t registered with Register_Class(), or inthe case of modules and channels, with Define_Module()/Define_Channel()”

在Txc1中重定义了函数 initialize() 和handleMessage() ,他们从仿真内核调用 ,第一个函数仅仿真开始时调用一次,第二个函数当有一个消息到达该模块时就会进行调用。

在 initialize() 函数中,创建了一个消息对象 cMessage ,并通过门 out 发送出去. 如果这个门连接到其他模块的 input门 ,仿真内核将传输这个消息到另一个模块的 handleMessage() ,根据 NED文件中的链接有100ms的传播时延。另一个模块将会将其传回,构成一个乒乓一般的传播。

消息(数据包、帧、作业等)和事件(计时器、超时)都是由 OMNeT++ 中的 cMessage 对象(或其子类)表示。 发送或调度它们后,它们将保持在仿真内核的“计划事件”或“未来事件”列表中,直到时间到了,他们才会通过 handleMessage()传输到模块。

注意:这个仿真没有内置停止条件,但可以哦那个GUI中停止。

添加 omnetpp.ini

为了运行这个仿真,我们要创建一个 omnetpp.ini文件,该文件告诉仿真程序想要仿真的网络是哪一个(NED文件可能包括多个网络),通过该文件还可以传递参数到模型中,显式的为随机数生成器指明seeds等。
在这里插入图片描述

在这里插入图片描述
与 NED的编辑器类似,ini文件的编辑器也有两个模式,Form和Source ,前者适合配置仿真内核,后者适合输入仿真参数。

现在选择Source,输入如下代码:

[General]
network = Tictoc1

现在已经完成了第一个模型的创建,接下来准备编译和运行该模型。

总结

通过该流程的学习,我们了解到一个模型的创建包含了三类主要文件 : ned 、cpp和ini 。 ned文件构建模块和网络,可以通过图形化界面或文本输入构建 ,cpp文件编程各个模块的具体功能 ,ini文件确定运行那个网络或传递参数等。

除了学习到创建各个文件的用途、创建方式、命名规则等。还学习到cMessage 、initialize()函数、handleMessage()函数相关的知识。进一步学习ned语言可以通过官方文档。在cpp文件中使用 omnetpp.h头文件和 omnetpp命名空间,可以进一步学习。

运行仿真

启动仿真程序

选择 omnetpp.ini文件 ,点击 Run按钮即可开始仿真
在这里插入图片描述

运行仿真

构建并启动仿真后,会弹出一个新界面
在这里插入图片描述
该窗口属于 Qtenv,是OMNeT++仿真运行时主要的 GUI。
在图形化窗口中,可以看见 tic和toc

点击最上面一栏的Run可以运行仿真,可以看见tic和toc相互交换信息的过程。
在这里插入图片描述
主窗口工具栏显示当前仿真时间。这是虚拟时间, 它与程序所需的实际(或挂钟)执行时间无关 。 实际上,在现实世界的一秒钟内可以模拟多少秒 很大程度上取决于硬件的速度,甚至更多地取决于硬件的性质和 仿真模型本身的复杂性。
在这里插入图片描述

比如硬件较差的情况下,仿真中只过去了一秒而实际时间耗费了五分钟。

请注意,节点处理消息所需的模拟时间为零。 在这个模型中,唯一使仿真时间流逝的是 连接上的传播延迟。

通过顶部的滑块,可以减慢或加速动画的速度。
在这里插入图片描述
F8 :停止仿真
F4:单步执行
F5:有动画仿真
F6:无动画仿真
F7:快速模式 ,将完全关闭追踪特征

可以多次运行该仿真来探索各个按钮的功能,直接点X可以退出该仿真

调试

模拟只是一个 C++ 程序,因此,它通常需要 在开发过程中进行调试。在本节中,我们将了解 调试的基础知识,以帮助您完成这项重要任务。

点击调试按钮开始进行调试
在这里插入图片描述
这将导致仿真程序在调试器下启动 (通常为 gdb)。IDE 也将切换到 “Debug perspective”, 即将其各种窗格和视图重新排列为更好的布局 适合调试。您可以使用工具栏上的“终止”按钮(红色方块)结束调试会话。

运行时错误

最常见的debug是在运行时出错,我们现在模拟一个错误,在txc1.cc的handleMessage()函数中的 多加一个send()函数,如下所示:

void Txc1::handleMessage(cMessage *msg)
{
    //...
    send(msg, "out"); // send out the message
    send(msg, "out"); // THIS SHOULD CAUSE AN ERROR
}

此时再运行会报如下的错:
在这里插入图片描述
现在,在调试模式下运行仿真。由于debug-on-errors选项 默认情况下启用,仿真程序将在调试器中停止。
在这里插入图片描述
可以通过检查堆栈跟踪(嵌套的列表)来定位错误
在这里插入图片描述
注:右上角的两个小按钮可以切换debug和普通模式
在这里插入图片描述
你可以看到是omnet++的breakIntoDebuggerIfRequested()方法激活了调试器。然后,你需要搜索一个看起来熟悉的函数,即模型的一部分。在我们的例子中,这就是Txc1::handleMessage()。选择这一行将在编辑器区域中显示相应的源代码,并允许您在variables视图中检查变量的值。这些信息将帮助您确定错误的原因并修复它。

崩溃

让我们来制造一个崩溃,先恢复之前对handleMessage()函数的编辑,假装我们在发送消息之前忘记创建它,在initialize()函数中修改原来的行为:

        cMessage *msg; // no initialization!
        send(msg, "out");

此时运行该仿真,将会造成崩溃。
在这里插入图片描述
该报错也可能是:Simulation terminated with exit code: 139

然后在debug模式下运行该代码,然后就可以定位到出错的位置,同时可以查看变量窗口中的变量,帮助进一步修复错误
在这里插入图片描述

断点

您还可以手动在代码中放置断点。断点将停止执行,并允许您检查变量、逐行执行代码或恢复执行(直到下一个断点)。

双击编辑器中左侧的gutter,或者从上下文菜单中选择Toggle breakpoint,可以将断点置于源代码中的特定行。可以在breakpoints视图中检查活动(和不活动)断点的列表。

调试下一事件

如果您做过前面的练习,您一定已经注意到,在Txc1简单模块中的每个事件上都触发了断点。在现实生活中,通常只有在模块的第357个事件时才会出现错误,所以理想情况下,应该从这个时候开始调试。要点击简历356次才能找到错误的位置是很不方便的。一种可能的解决方案是向断点添加条件或忽略计数(请参阅上下文菜单中的断点属性)。然而,可能有一个更方便的解决方案。

在Qtenv中,使用Run Until获取要调试的事件。然后,从菜单中选择“模拟->调试下一个事件”。这将在调试器中在下一个事件的handleMessage()开始处触发一个断点,你可以开始调试该事件。

在这里插入图片描述

调试/运行 日志

重新启动仿真

当你用IDE工具栏上的Run或Debug按钮启动模拟程序时,与启动相关的设置会保存在启动配置中。启动配置可以在运行/调试配置对话框中查看,可以通过单击运行(调试)工具栏按钮旁边的向下小箭头来打开菜单,并选择运行(调试)配置…在里面。在相同的菜单中,您还可以单击启动配置的名称(例如tictoc),同时按住Ctrl键打开相应配置的对话框。

该对话框允许您激活各种启动设置。
在这里插入图片描述

在这里插入图片描述

序列图可视化

omnet++仿真内核可以将仿真过程中的消息交换记录到事件日志文件中。要启用记录事件日志,请在启动配置对话框中选中Record eventlog复选框。或者,您可以在omnetpp.ini中指定Record -eventlog = true,甚至在启动后在Qtenv图形运行时环境中使用Record按钮,
在这里插入图片描述

稍后可以使用IDE中的序列图工具分析日志文件。项目文件夹下的results目录中包含 .elog 文件。在omnet++ IDE中双击它会打开序列图工具,以及窗口底部的event log选项卡。
在这里插入图片描述
在这里插入图片描述

注意:产生的日志文件可能会非常大,所以最好只在特别需要时使用该功能

下图是使用序列图工具创建的,显示了消息如何在网络中的不同节点之间路由。在这种情况下,图表非常简单,但当你有一个复杂的模型时,序列图在调试、探索或记录模型的行为方面非常有价值。

  • 30
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OMNeT++仿真AODV(Ad hoc On-Demand Distance Vector)路由协议的步骤如下: 1. 安装OMNeT++:首先,下载OMNeT++并按照指示完成安装。 2. 下载AODV模型:从OMNeT++的官方网站或其他可靠来源下载AODV模型。 3. 导入AODV模型到OMNeT++:将下载的AODV模型导入到OMNeT++,可以通过直接将文件复制到项目文件夹或打开OMNeT++并导入模型进行操作。 4. 配置仿真参数:在OMNeT++,打开AODV模型并设置仿真参数,例如节点数量、通信范围、数据速率等。 5. 设计网络拓扑:在仿真环境创建网络拓扑,设置节点位置和连通性。可以使用内置工具或自定义脚本程序进行创建。 6. 编写仿真代码:根据仿真需求,编写仿真代码以实现AODV协议的功能。 这可能包括启动节点、执行路由发现和维护过程、更新路由表、处理数据包转发等。 7. 运行仿真:保存并编译仿真代码后,使用OMNeT++运行仿真。 8. 分析仿真结果:在仿真结束后,分析仿真结果,包括路由表、数据包转发延迟、吞吐量等指标。 9. 调优和改进:根据仿真结果,调优和改进AODV协议的参数、算法等,或者尝试其他路由协议。 10. 重复步骤4-9:根据仿真需求和改进要求,重复执行步骤4到9,直到达到预期的仿真效果。 以上是在OMNeT++仿真AODV路由协议的基本步骤。在每个步骤,需要根据具体情况进行调整和改进,以达到预期的仿真结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月早十

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值