使用TicToc学习OMNeT++——第 1 部分 - 入门

系列文章目录

提示:本文是本系列教程的第2篇,前期准备工作请参考第1篇 :
使用TicToc学习OMNeT++——第 0 部分 - 简介


提示:本人的第2篇文章,写得不好,请读者多多包涵


前言

提示:这里说明了本文要记录的大概内容:

本文基于原版英文教程的第1部分:Part 1 - Getting Started进行翻译和论述,并结合仿真手册和AI问答以厘清基本概念。


提示:以下是本篇文章正文内容

一、原文翻译

原文经过本人的人工润色,主要对一些复杂嵌套的英文语句调整语序,修改一些术语翻译错误,然后是修正句内的修饰关系。此外,原文翻译中还补充了一些自己实操过程中的截图。

Part 1 - Getting Started 第 1 部分 - 入门

1.1 The model 1.1 模型

For a start, let us begin with a “network” that consists of two nodes. The nodes will do something simple: one of the nodes will create a packet, and the two nodes will keep passing the same packet back and forth. We’ll call the nodes tic and toc. Later we’ll gradually improve this model, introducing OMNeT++ features at each step.
首先,让我们从一个由两个节点组成的“网络”开始。节点将执行一些简单操作:其中一个节点将创建一个 数据包,两个节点将不断来回传递相同的 数据包。我们将节点称为 tictoc .稍后我们将逐步改进此模型,在每一步中引入 OMNeT++ 功能。

Here are the steps you take to implement your first simulation from scratch.
以下是您从头开始实施第一个模拟的步骤。

1.2 Setting up the project 1.2 设置项目

Start the OMNeT++ IDE by typing omnetpp in your terminal. (We assume that you already have a working OMNeT++ installation. If not, please install the latest version, consulting the Installation Guide as needed.) Once in the IDE, choose New -> OMNeT++ Project from the menu.
通过将 omnetpp 键入终端来启动 OMNeT++ IDE。(我们假设您已经有一个有效的 OMNeT++ 安装。如果没有,请安装最新版本,并根据需要查阅安装指南。进入 IDE 后,从菜单中选择 “New -> OMNeT++ Project”。
new_project
A wizard dialog will appear. Enter tictoc as project name,
将出现一个向导对话框。输入tictoc 作为项目名称,
项目名称
choose Empty project when asked about the initial content of the project, then click Finish.
在询问项目的初始内容时选择“空项目”,然后单击“完成”。
初始内容

An empty project will be created, as you can see in the Project Explorer. (Note: Some OMNeT++ versions will generate a package.ned file into the project. We don’t need it now: delete the file by selecting it and hitting Delete.)
将创建一个空项目,如您在 Project Explorer 中看到的那样。(注意:某些 OMNeT++ 版本会在项目中生成一个 package.ned 文件。我们现在不需要它:通过选择文件并点击 Delete 来删除文件。)
The project will hold all files that belong to our simulation. In our example, the project consists of a single directory. For larger simulations, the project’s contents are usually sorted into src/ and simulations/ folders, and possibly subfolders underneath them.
该项目将保存属于我们模拟的所有文件。在我们的示例中,项目由单个 目录 组成。对于较大的模拟,项目的内容通常被分类为 src/simulations/ 文件夹 ,可能还有它们下面的子文件夹。

Note 注意
Using the IDE is entirely optional. Almost all functionality of OMNeT++ (except for some very graphics-intensive and interactive features like sequence chart browsing and result plotting) is available on the command line. Model source files can be edited with any text editor, and OMNeT++ provides command-line tools for special tasks such as makefile creation, message file to C++ translation, result file querying and data export, and so on. To proceed without the IDE, simply create a directory and create the following NED, C++ and ini files in it with your favorite text editor.
使用 IDE 是完全可选的。OMNeT++ 的几乎所有功能(除了一些非常图形密集型的交互式功能,如序列图浏览和结果绘图)都可以在命令行上使用。模型源文件可以使用任何文本编辑器进行编辑,OMNeT++ 为特殊任务提供了命令行工具,例如创建 makefile、消息文件到 C++ 的转换、结果文件查询和数据导出等。要在没有 IDE 的情况下继续操作,只需创建一个目录,然后使用您喜欢的文本编辑器在其中创建以下 NED、C++ 和 ini 文件。

1.3 Adding the NED file 1.3 添加 NED 文件

OMNeT++ uses NED files to define components and to assemble them into larger units like networks. We start implementing our model by adding a NED file. To add the file to the project, right-click the project directory in the Project Explorer panel on the left, and choose New -> Network Description File (NED) from the menu.
OMNeT++ 使用 NED 文件来定义组件并将它们组装成更大的单元(如网络)。我们通过添加 NED 文件开始实现我们的模型。要将文件添加到项目中,请在左侧的“Project Explorer panel 项目资源管理器”面板中右键单击项目目录,然后从菜单中选择“New 新建 -> Network Description File 网络描述文件(NED)”。
添加NED文件

Enter tictoc1.ned when prompted for the file name.
当系统提示输入文件名时,请输入 tictoc1.ned 。
输入文件名
选择空文件作为模板
选择模板
Once created, the file can be edited in the Editor area of the OMNeT++ IDE. The OMNeT++ IDE’s NED editor has two modes, Design and Source; one can switch between them using the tabs at the bottom of the editor. In Design mode, the topology can be edited graphically, using the mouse and the palette on the right. In Source mode, the NED source code can be directly edited as text. Changes done in one mode will be immediately reflected in the other, so you can freely switch between modes during editing, and do each change in whichever mode it is more convenient. (Since NED files are plain text files, you can even use an external text editor to edit them, although you’ll miss syntax highlighting, content assist, cross-references and other IDE features.)
创建后,可以在 OMNeT++ IDE 的 “Editor”(编辑器)区域中编辑该文件。OMNeT++ IDE 的 NED 编辑器有两种模式:Design 和 Source;可以使用编辑器底部的选项卡在它们之间切换。在“设计”模式下,可以使用鼠标和右侧的组件盘以图形方式编辑拓扑。在源模式下,NED源码可以直接编辑为文本。在一种模式下完成的更改将立即反映在另一种模式中,因此您可以在编辑过程中在模式之间自由切换,并以更方便的模式进行每次更改。(由于 NED 文件是纯文本文件,您甚至可以使用外部文本编辑器来编辑它们,尽管您会错过语法高亮、内容辅助、交叉引用和其他 IDE 功能。)

Switch into Source mode, and enter the following:
切换到源模式,然后输入以下内容:

//  定义了简单模块类型 Txc1 在网络中的结构,行为则由 txc1.cc 中的 Txc1 类 定义
simple Txc1{	// TXC代表Transmit Clock,即发送时钟?
    gates:
        input in;
        output out;
}

//
// Two instances (tic and toc) of Txc1 connected both ways. Txc1的两个实例(tic和toc)双向连接。
// Tic and toc will pass messages to one another. Tic和toc会互相传递信息。
//

//  定义了 1种特殊的复合模块类型(网络模型) Tictoc1 在网络中的结构,复合模块的行为本质上都是简单模块的行为
network Tictoc1 // Tictoc1
{
    submodules:
        tic: Txc1;  // tic是 在复合模块类型 Tictoc1 的定义中 声明的 简单模块类型 Txc1 的一个实例
        toc: Txc1;
    connections:
        tic.out --> { delay = 100ms;} --> toc.in;
        tic.in <-- { delay = 100ms;} <-- toc.out;
}

When you’re done, switch back to Design mode. You should see something like this:
完成后,切换回“设计”模式。您应该看到如下内容:
设计模式
The first block in the file declares Txc1 as a simple module type. Simple modules are atomic on NED level. They are also active components, and their behavior is implemented in C++. The declaration also says that Txc1 has an input gate named in, and an output gate named out.
文件中的第一个块声明 Txc1 为简单模块类型。简单模块在NED级别上是 原子的。它们也是活动组件,它们的行为是在 C++ 中实现的。该声明还说, Txc1 有一个名为 in 的输入门和一个名为 out 的输出门。

The second block declares Tictoc1 as a network. Tictoc1 is assembled from two submodules, tic and toc, both instances of the module type Txc1. tic’s output gate is connected to toc’s input gate, and vice versa. There will be a 100ms propagation delay both ways.
第二个块声明 Tictoc1 为网络。 Tictoc1 由两个子模块组装而成, tic 并且 toc 都是模块类型的 Txc1 实例。 tic 的输出门连接到 toc 的输入门,反之亦然。双向传播延迟为 100 毫秒。

Note 注意
You can find a detailed description of the NED language in the OMNeT++ Simulation Manual. (The manual can also be found in the doc directory of your OMNeT++ installation.)
您可以在 OMNeT++ 仿真手册中找到 NED 语言的详细说明。(该手册也可以在 OMNeT++ 安装 doc 目录中找到。

1.4 Adding the C++ files 1.4 添加 C++ 文件

We now need to implement the functionality of the Txc1 simple module in C++. Create a file named txc1.cc by choosing New -> Source File from the project’s context menu (or File -> New -> File from the IDE’s main menu),
我们现在需要在 C++ 中实现 Txc1 简单模块的功能。通过从项目的上下文菜单中选择 “New -> Source File”(或从 IDE 的主菜单中选择 “File -> New -> File”)来创建名为 txc1.cc “文件”的文件,
添加C++文件

and enter the following content:
然后输入以下内容:

/*
 * txc1.cc
 *
 *  Created on: 2023年9月25日
 *      Author: lvihe
 */
#include<string.h>
#include<omnetpp.h>

using namespace omnetpp;

/**
 * Derive the Txc1 class from cSimpleModule. In the Tictoc1 network, 从cSimpleModule派生Txc1类。在Tictoc1网络中,    冒号在大括号外面表示继承父类或自基类派生
 * both the `tic' and `toc' modules are Txc1 objects, created by OMNeT++ "tic"和"toc"模块都是Txc1对象,由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++ 模块类需要向OMNeT++注册,以供仿真核心使用
Define_Module(Txc1);

void Txc1::initialize()
{
    // Initialize is called at the beginning of the simulation. Initialize会在模拟仿真开始时被调用。
    // To bootstrap the tic-toc-tic-toc process, one of the modules needs 要引导tic-toc-tic-toc过程,其中一个模块需要
    // to send the first message. Let this be `tic'. 发送第一条消息。让此模块为"tic"。

    // Am I Tic or Toc? //我是Tic还是Toc?   通过getName函数(应该是从cSimpleModule类继承的成员函数)获取Txc1的类实例的名称,如果为"tic",则生成消息并第一次发送
    if(strcmp("tic", getName()) == 0){
        // create and send first message on gate "out". "tictocMsg" is an 在"out"门上创建并发送第一条消息。"tictocMsg"是
        // arbitrary string which will be the name of the message object. 将作为消息对象名称的任意字符串。
        cMessage *msg = new cMessage("tictocMsg");  // 堆上创建的对象生命周期超过其定义的作用域,直到显式地使用delete来释放内存,对象都会一直存在,此时可以在函数或代码块之外访问它
        //cMessage *msg; // no initialization! 没初始化!
        send(msg, "out");
    }
}

void Txc1::handleMessage(cMessage *msg)
{
    // The handleMessage() method is called whenever a message arrives  每当消息到达时,都会在模块处调用 handleMessage()方法
    // at the module. Here, we just send it to the other module, through 在这里,我们只是通过门“out”将它发送到另一个模块。
    // gate `out'. Because both `tic' and `toc' does the same, the message  由于'tic'和'toc'的作用相同
    // will bounce between the two.  消息将在两者之间反弹。
    send(msg, "out");// send out the message  发出消息,这里的msg指向 调用tic.initialize()的过程中 动态创建的cMessage对象!
    //send(msg, "out"); // THIS SHOULD CAUSE AN ERROR  这应该会引起错误
}



The Txc1 simple module type is represented by the C++ class Txc1. The Txc1 class needs to subclass from OMNeT++'s cSimpleModule class, and needs to be registered in OMNeT++ with the Define_Module macro.
Txc1 简单模块类型由 C++ 类 Txc1 表示。该 Txc1 类 继承自 OMNeT++的 cSimpleModule 类 ,并且需要在 OMNeT++ 中使用 Define_Module 宏注册

Note 注意
It is a common mistake to forget the Define_Module line. If it is missing, you’ll get an error message similar to this one: "Error: Class 'Txc1' not found -- perhaps its code was not linked in, or the class wasn't registered with Register_Class(), or in the case of modules and channels, with Define_Module/Define_Channel()".
忘记 Define_Module 行 是一个常见的错误。如果缺少,您将收到类似于 这个 的错误消息:"Error: Class 'Txc1' not found -- perhaps its code was not linked in, or the class wasn't registered with Register_Class(), or in the case of modules and channels, with Define_Module/Define_Channel()" 。

We redefine two methods from cSimpleModule: initialize() and handleMessage(). They are invoked from the simulation kernel: the first one only once, and the second one whenever a message arrives at the module.
我们重新定义了来自 cSimpleModule 的两个方法: initialize()handleMessage() 。它们从模拟内核调用:第一个只调用一次,第二个在消息到达模块时调用。

In initialize() we create a message object (cMessage), and send it out on gate out. Since this gate is connected to the other module’s input gate, the simulation kernel will deliver this message to the other module in the argument to handleMessage() – after a 100ms propagation delay assigned to the link in the NED file. The other module just sends it back (another 100ms delay), so it will result in a continuous ping-pong.
initialize() 中,我们创建一个消息对象(cMessage),并在门 out 上将其发送出去。由于此门连接到另一个模块的输入门,因此仿真内核将 在 分配给 NED 文件中的链路的 100 毫秒传播延迟 后,将此消息传递到另一个模块 以传入handleMessage()的参数的形式 。另一个模块只是将其发送回去(另一个 100 毫秒延迟),因此将导致连续的 乒乓(过程)。

Messages (packets, frames, jobs, etc) and events (timers, timeouts) are all represented by cMessage objects (or its subclasses) in OMNeT++. After you send or schedule them, they will be held by the simulation kernel in the “scheduled events” or “future events” list until their time comes and they are delivered to the modules via handleMessage().
消息(数据包、帧、作业等)和事件(计时器、超时)都由 OMNeT++ 中的 cMessage 对象(或其子类)表示。发送或调度它们后,它们将由仿真内核保存在“调度事件”或“未来事件”列表中,直到它们的时间到来,并通过 handleMessage() 将它们传递到模块。

Note that there is no stopping condition built into this simulation: it would continue forever. You will be able to stop it from the GUI. (You could also specify a simulation time limit or CPU time limit in the configuration file, but we don’t do that in the tutorial.)
请注意,此模拟中没有内置停止条件:它将永远持续下去。您将能够从 GUI 中停止它。(您也可以在配置文件中指定模拟时间限制或 CPU 时间限制,但我们在本教程中没有这样做。)

1.5 Adding omnetpp.ini 1.5 添加omnetpp.ini

To be able to run the simulation, we need to create an omnetpp.ini file. omnetpp.ini tells the simulation program which network you want to simulate (as NED files may contain several networks), you can pass parameters to the model, explicitly specify seeds for the random number generators, etc.
为了能够运行模拟,我们需要创建一个 omnetpp.ini 文件。 omnetpp.ini 告诉仿真程序你要仿真哪个网络(因为NED文件可能包含多个网络),你可以将参数传递给模型,显式指定随机数生成器的种子,等等。

Create an omnetpp.ini file using the File -> New -> Initialization file (INI) menu item.
使用“文件”->“新建”->初始化文件 (INI) 菜单项创建 omnetpp.ini 文件。
添加INI文件

The new file will open in an Inifile Editor. As the NED Editor, the Inifile Editor also has two modes, Form and Source, which edit the same content. The former is more suitable for configuring the simulation kernel, and the latter for entering module parameters.
新文件将在 Inifile 编辑器中打开。作为 NED 编辑器,Inifile 编辑器还具有两种模式,即 Form 和 Source,它们编辑相同的内容。前者更适合配置仿真内核,后者更适合输入模块参数。

For now, just switch to Source mode and enter the following:
现在,只需切换到源模式并输入以下内容:

[General]
network = Tictoc1

You can verify the result in Form mode:
您可以在表单模式下验证结果:
表单模式
tictoc2 and further steps will all share a common omnetpp.ini file.
tictoc2 和进一步的步骤将共享一个通用的omnetpp.ini文件。

We are now done with creating the first model, and ready to compile and run it.
现在,我们已经完成了第一个模型的创建,并准备编译和运行它。

Sources: tictoc1.ned, txc1.cc, omnetpp.ini
源(代码):tictoc1.ned, txc1.cc, omnetpp.ini

二、补充内容

对于教程中涉及到的概念,本人查阅仿真手册得到的相关内容。以及询问AI得到的回答。

1. NED和INI文件的本质

根据2.3.1.1节(Running the Simulation and Analyzing the Results)的第1段:

“ 当程序启动时,它首先读取 NED 文件,然后读取通常称为 omnetpp.ini 的配置文件。配置文件包含 控制 仿真的执行方式、模型参数值等 的设置。配置文件还可以 规定 多个模拟运行;在最简单的情况下,它们将由模拟程序一个接一个地执行。”
也是就说NED文件和INI文件本质上是仿真程序启动后的输入文件,这两者本质上都是在cpp文件中定义的类实例构造函数的参数?

来自AI的回答:

您的理解基本正确,但有一些细微的差别需要澄清。

NED(Network Description Language)文件和INI文件在OMNeT++仿真中确实扮演着输入文件的角色,但它们与C++类实例构造函数的参数之间的关系并不是直接的。

NED文件定义了网络模型的结构和模块类型。这些模块类型与C++中定义的模块类相关联。当仿真程序启动时,它会读取NED文件,并根据其中定义的结构和模块类型来构建仿真模型。然而,NED文件本身并不直接包含传递给C++类构造函数的参数。这些参数通常是在INI配置文件中定义的。

INI配置文件(通常命名为omnetpp.ini)用于设置仿真的执行方式和模型参数值。它包含了控制仿真运行的各种参数,这些参数可以影响仿真模型的行为或控制仿真过程的不同方面。这些参数可能与C++类实例的构造函数参数相关,但它们并不是直接作为构造函数的参数传递的。相反,在仿真初始化阶段,OMNeT++的仿真内核会读取INI文件,解析其中的参数,并将这些参数值传递给相应的模块实例。这通常是通过调用模块的初始化函数(如initialize())来完成的,而不是直接传递给构造函数。

因此,可以说NED文件和INI文件是仿真程序启动后的输入文件,它们提供了构建和配置仿真模型所需的信息。然而,这些文件与C++类实例构造函数的参数之间的关系是间接的,它们通过OMNeT++的仿真内核和初始化机制来影响模块实例的创建和配置。

2 宏注册

根据4.3.1节和4.3.2节

简单模块类必须通过 Define_Module() 宏向 OMNeT++ 注册是什么意思?

来自AI的回答:

Define_Module()宏是OMNeT++框架提供的一个机制,用于将模块类与OMNeT++的仿真核心连接起来。当仿真运行时,OMNeT++需要知道有哪些模块类可用,以及这些类的属性和行为。通过Define_Module()宏,OMNeT++可以获取到这些信息,并在仿真过程中正确地创建和配置模块实例。


总结

提示:这里对文章进行总结:

终于完成了入门篇,也许并没有什么大的用处,但也是一种自我学习的过程,也是对自己的学习心得的一种记录,最后如果能对读者有点用处的话,那就再好不过了😂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值