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

    • introduce
    • 开始
      • 模型介绍
      • 构建项目
      • 添加 NED 文件
      • 添加C++ 文件
      • 添加 omnetpp.ini
      • 总结
    • 运行仿真
      • 启动仿真程序
      • 运行仿真
      • 调试
        • 运行时错误
        • 崩溃
        • 断点
        • 调试下一事件
      • 调试/运行 日志
      • 序列图可视化

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 messagesend(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选项卡。
在这里插入图片描述
在这里插入图片描述

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/597911.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity Toggle组件

Toggle Group组件 Allow Switch Off属性值为false时&#xff0c; 1&#xff0c;Toggle初始时默认会有一个被勾选&#xff08;ison为true&#xff09;&#xff0c;可以自己打勾指定 2&#xff0c;不能取消勾选 Allow Switch Off属性值为true时&#xff0c; 1&#xff0c;Toggl…

第十四届蓝桥杯岛屿个数

题目描述&#xff1a; 小蓝得到了一副大小为 MN 的格子地图&#xff0c;可以将其视作一个只包含字符 0&#xff08;代表海水&#xff09;和 1&#xff08;代表陆地&#xff09;的二维数组&#xff0c;地图之外可以视作全部是海水&#xff0c;每个岛屿由在上/下/左/右四个方向上…

C++:类与对象(一)

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《C&#xff1a;类与对象&#xff08;一&#xff09;》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 文章目录 面向对象和面向过程的区别1.类的引入2.…

调用飞书获取用户Id接口成功,但是没有返回相应数据

原因&#xff1a; 该自建应用没有开放相应的数据权限。 解决办法&#xff1a; 在此处配置即可。

Codeforces Round 932 (Div. 2) ---- F. Andrey‘s Tree ---- 题解

F. Andreys Tree&#xff1a; 题目描述&#xff1a; 思路解析&#xff1a; 我们假设删除任意一个结点后&#xff0c;我们会将整个树切分为k个联通块&#xff0c;那么可以明确的知道我们只需要连接(k-1)条边就可以将这k个联通块重新连为一棵树。 那么最小代价是啥呢? 图解分…

linux 安装JDK

一、安装jdk mkdir -p /export/servers # 软件安装的目录 0 . 使用rpm -qa | grep java 查看是否已经安装了jdk 使用: rpm -e --nodeps 软件的名称 将jdk进行卸载 执行完成后, 查看是否全部删除: 需要解压jdk的压缩包 tar -zxvf jdk-8u144-linux-x64.tar.gz -C /export/s…

如何利用AI制作Twitter推文

智能生活新体验&#xff1a;最新会话式AI如何让您的日常更便捷 人工智能制作Twitter推文时&#xff0c;会运用多种策略确保推文既简洁又有影响力。首先&#xff0c;人工智能会分析大量数据来理解不同话题的流行趋势、热门话题标签和目标受众的偏好。接着&#xff0c;它会根据这…

嵌入式面向对象学习 RT-Thread I/O 设备管理框架 设备驱动层 案例测试

嵌入式面向对象 RT-Thread I/O 设备管理框架 设备驱动层 注&#xff1a;本文介绍性内容转载于《RT-Thread记录&#xff08;十、全面认识 RT-Thread I/O 设备模型&#xff09;》 注&#xff1a; 本次使用的开发板 &#xff1a; ​ 兆易创新GD32F407VET6开发板 ​ 雅特力科技…

3D模型缩略:创造简洁而有效的呈现---模大狮模型网

在3D设计和渲染中&#xff0c;有时候我们需要在有限的空间内展示复杂的场景或模型。在这种情况下&#xff0c;将整个模型完整地呈现出来可能会显得过于拥挤或混乱。因此&#xff0c;使用缩略图是一种常见且有效的方法&#xff0c;可以简化场景&#xff0c;突出重点&#xff0c;…

第十讲 Query Execution Part 1

1 处理模型【Processing Model】 DBMS 的处理模型【Processing Model】定义了系统如何执行【execute】查询计划【Query Plan】。 针对不同的工作负载进行不同的权衡。 方法1&#xff1a;迭代器模型【Iterator Model】 方法2&#xff1a;物化模型【Materialization Model】 方…

HTML基础知识详解(下)(如果想知道html的全部基础知识点,那么只看这一篇就足够了!)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经学习完了超链接标签、列表标签和表格标签&#xff0c;但是我们还有一些标签没有学习&#xff0c;在这篇文章中&#xff0c;我们将学习剩余的标签。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页…

Spring Boot集成JWT快速入门demo

1.JWT是什么&#xff1f; JWT&#xff0c;英文全称JSON Web Token&#xff1a;JSON网络令牌。为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准(RFC 7519)。这个规范允许我们使用JWT在客户端和服务端之间传递安全可靠的信息。JWT是一个轻便的安全跨平台传输格式&am…