Oment++ 初学者教程 第4节-将其转变为真实网络
4.1两个以上的节点
现在,我们将迈出一大步:创建几个tic
模块并将它们连接到网络中。现在,我们将使它们的工作变得简单:一个节点生成一条消息,其他节点继续沿随机方向扔消息,直到它到达预定的目标节点为止。NED文件将需要进行一些更改。首先,该Txc
模块将需要具有多个输入和输出门:
simple Txc10
{
parameters:
@display("i=block/routing");
gates:
input in[]; //声明input,ouput两种类型的gate数组
output out[];
}
数组[ ]
多个门变成gate向量。向量的大小(门数)将在我们使用Txc构建网络的地方确定。
network Tictoc10
{
submodules:
tic[6]: Txc10;
connections:
tic[0].out++ --> { delay = 100ms; } --> tic[1].in++;
tic[0].in++ <-- { delay = 100ms; } <-- tic[1].out++;
tic[1].out++ --> { delay = 100ms; } --> tic[2].in++;
tic[1].in++ <-- { delay = 100ms; } <-- tic[2].out++;
tic[1].out++ --> { delay = 100ms; } --> tic[4].in++;
tic[1].in++ <-- { delay = 100ms; } <-- tic[4].out++;
tic[3].out++ --> { delay = 100ms; } --> tic[4].in++;
tic[3].in++ <-- { delay = 100ms; } <-- tic[4].out++;
tic[4].out++ --> { delay = 100ms; } --> tic[5].in++;
tic[4].in++ <-- { delay = 100ms; } <-- tic[5].out++;
}
在这里,我们创建了6个模块作为模块向量,并将它们连接起来。
生成的拓扑如下所示:
在此版本中,tic[0]
将生成要发送的消息。这是在函数initialize()
的帮助下完成的,该getIndex()
函数返回向量中模块的索引。
代码的forwardMessage()
实质是handleMessage()
每当消息到达节点时我们从中调用的函数。它绘制一个随机的gate number,并在该gate上发送message。
void Txc10::forwardMessage(cMessage *msg)
{
// 我们选择随机的一个gate发送信息
// 我们在0~out[]数组长度之间选择一个随机数
int n = gateSize("out");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on port out[" << k << "]\n";
send(msg, "out", k);
}
当消息到达时tic[3]
,handleMessage()
它将删除该消息。
请参阅txc10.cc中的完整代码
练习
您会注意到,这种简单的“路由”效率不是很高:通常,数据包会在两个节点之间不断跳动一段时间,然后再发送到另一个方向。如果节点不将数据包发送回发送方,则可以在某种程度上进行改进。实现这一点。提示:cMessage::getArrivalGate()
, cGate::getIndex()
。请注意,如果消息不是通过门到达的,而是self-messages,则getArrivalGate()
返回NULL
。
来源:tictoc10.ned,txc10.cc,omnetpp.ini
4.2信道和内部类型定义
我们新的网络定义变得非常复杂冗余,尤其是连接部分。让我们尝试简化它。我们注意到的第一件事是,连接始终使用相同的delay
参数。与简单模块类似,可以为连接创建类型(它们称为信道)。我们应该创建一个指定延迟参数的信道类型,并将该类型用于网络中的所有连接。
network Tictoc11
{
types:
channel Channel extends ned.DelayChannel {
delay = 100ms;
}
submodules:
如您所见,我们通过添加一个types
字段在网络定义中定义了新的信道类型。此类型定义仅在网络内部可见。它称为局部或内部类型。如果愿意,您也可以将简单模块用作内部类型。
笔记
我们通过专门内置来创建通道DelayChannel
。(可以在ned
包内找到内置信道。这就是为什么我们在extends
关键字后使用完整类型名称的ned.DelayChannel的原因
)
现在,让我们检查一下该connections
部分是如何更改的。
connections:
tic[0].out++ --> Channel --> tic[1].in++;
tic[0].in++ <-- Channel <-- tic[1].out++;
tic[1].out++ --> Channel --> tic[2].in++;
tic[1].in++ <-- Channel <-- tic[2].out++;
tic[1].out++ --> Channel --> tic[4].in++;
tic[1].in++ <-- Channel <-- tic[4].out++;
tic[3].out++ --> Channel --> tic[4].in++;
tic[3].in++ <-- Channel <-- tic[4].out++;
tic[4].out++ --> Channel --> tic[5].in++;
tic[4].in++ <-- Channel <-- tic[5].out++;
}
如您所见,我们仅在连接定义内指定通道名称。这样可以轻松更改整个网络的延迟参数。
来源:tictoc11.ned,txc11.cc,omnetpp.ini
4.3使用双向连接
如果再检查一下该connections
部分,我们将意识到每个节点对都通过两个连接连接。每个方向一个。OMNeT ++ 4支持两种方式的连接,因此让我们使用它们。
首先,我们必须定义双向(或所谓的inout
)门,而不是之前使用的分离input
和output
门。
simple Txc12
{
parameters:
@display("i=block/routing");
gates:
inout gate[]; // declare two way connections
}
新connections
部分如下所示:
connections:
tic[0].gate++ <--> Channel <--> tic[1].gate++;//tic[0].gate[0]<-->tic[1].gate[0]
tic[1].gate++ <--> Channel <--> tic[2].gate++;//tic[1].gate[1]<-->tic[2].gate[1]
tic[1].gate++ <--> Channel <--> tic[4].gate++;
tic[3].gate++ <--> Channel <--> tic[4].gate++;
tic[4].gate++ <--> Channel <--> tic[5].gate++;
}
我们已经修改了门名称,因此我们必须对C ++代码进行一些修改。
void Txc12::forwardMessage(cMessage *msg)
{
// In this example, we just pick a random gate to send it on.
// We draw a random number between 0 and the size of gate `gate[]'.
int n = gateSize("gate");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on gate[" << k << "]\n";
// $o and $i 后缀被用来识别门的双向输入输出
send(msg, "gate$o", k);
}
笔记
gate名称后的特殊$i和$o后缀允许我们分别使用连接的两个方向。
来源:tictoc12.ned,txc12.cc,omnetpp.ini
4.4定义我们的message class
在此步骤中,不再对目标地址进行硬编码tic[3]
-我们绘制一个随机目标,然后将目标地址添加到消息中。
最好的方法是重写cMessage的子类并将目标添加为数据成员。手动编码消息类通常很乏味,因为它包含许多样板代码,因此我们让OMNeT ++为我们生成该类。消息类规范位于tictoc13.msg
:
message TicTocMsg13
{
int source;
int destination;
int hopCount = 0;
}
笔记
有关消息的更多详细信息,请参见OMNeT ++手册的第6节。
设置makefile以便调用消息编译器opp_msgc并生成消息声明tictoc13_m.h
并tictoc13_m.cc
从消息声明生成(文件名是根据tictoc13.msg
文件名而不是消息类型名生成的)。它们将包含一个TicTocMsg13
从[ cMessage
]子类生成的类;该类将为每个字段提供getter和setter方法。
我们将tictoc13_m.h
在我们的C ++代码中包含该代码,并且可以将其TicTocMsg13
用作任何其他类。
#include "tictoc13_m.h"
例如,我们使用以下几行generateMessage()
来创建消息并填写其字段。
TicTocMsg13 *msg = new TicTocMsg13(msgname);
msg->setSource(src);
msg->setDestination(dest);
return msg;
然后,handleMessage()
像这样开始:
void Txc13::handleMessage(cMessage *msg)
{
TicTocMsg13 *ttmsg = check_and_cast<TicTocMsg13 *>(msg);
if (ttmsg->getDestination() == getIndex()) {
在handleMessage()的参数中,我们将消息作为cMessage*
指针。但是,只有TicTocMsg13
将msg转换为时,我们才能访问在中定义的字段TicTocMsg13*
。纯C样式的强制转换((TicTocMsg13 *)msg
)是不安全的,因为如果消息_不是_a TicTocMsg13
,则程序最终将崩溃,从而导致错误,而这是很难发现的。
C ++提供了一种称为的解决方案dynamic_cast
。在这里,我们使用check_and_cast<>()
OMNeT ++提供的功能:它尝试通过强制转换指针dynamic_cast
,如果失败,则会通过错误消息停止模拟,类似于以下内容:
在下一行中,我们检查目标地址是否与节点的地址相同。该getIndex()
成员函数返回子模块向量模块的索引(记住,在我们声明是NED文件tic[6]: Txc13
,所以节点地址0..5)。
为了使模型的执行时间更长,在消息到达其目标之后,目标节点将生成另一条具有随机目标地址的消息,依此类推。阅读完整的代码:txc13.cc
运行模型时,它将如下所示:
您可以单击消息以在检查器窗口中查看其内容。双击将在新窗口中打开检查器。(您必须为此暂时停止模拟,或者要非常快地处理鼠标)。检查器窗口显示许多有用的信息;消息字段可/以在“_目录”_页面上看到。
来源:tictoc13.ned,tictoc13.msg,txc13.cc,omnetpp.ini
练习
在此模型中,在任何给定时刻只有一条消息正在运行:节点仅在另一条消息到达它们时才生成一条消息。我们这样做是为了使跟踪仿真变得更加容易。更改模块类,以便改为定期生成消息。消息之间的间隔应该是一个模块参数,返回指数分布的随机数。
Oment++ 初学者教程 第4节-将其转变为真实网络的更多相关文章
- Go GraphQL初学者教程
Go GraphQL初学者教程 https://tutorialedge.net/golang/go-graphql-beginners-tutorial/ https://tutorialedge. ...
- MapServer Tutorial——MapServer7.2.1教程学习——第一节:MapServer的基本配置管理,静态地图应用以及MapFile文件
MapServer Tutorial——MapServer7.2.1教程学习——第一节:MapServer的基本配置管理,静态地图应用以及MapFile文件 前言 万事开头难,有了<MapSer ...
- Easyui + asp.net MVC 系列教程 第19-23 节 完成注销 登录限制过滤 添加用户
前面视频 文章地址 Easyui + asp.net MVC 系列教程 第09-17 节 完成登录 高清录制 Easyui + asp.net mvc + sqlite 开发教程(录屏)适合入门 ...
- 《SLAM for Dummies》中文版《SLAM初学者教程》
SLAM for Dummies SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping 一本关于实时定位及绘图 ...
- SLAM for Dummies SLAM初学者教程 中文翻译 1到4章
SLAM for Dummies SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping 一本关于实时定位及绘图 ...
- PANDAS 数据分析初学者教程
Pandas 初学者教程 2018-05-19 六尺巷人 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非常重要的Python包.它不仅提供了很多方法,使得数据处理非常 ...
- OMnet++ 初学者教程 第一节 入门
第1部分-入门 1.1模型 首先,让我们从一个包含两个节点的"network"开始.节点将做一些简单的事情:一个是节点将创建一个数据包,而两个节点将继续来回传递相同的数据包.我们将 ...
- Github初学者教程(一)
如果你是一名程序员,或者是相关专业的学生,那么Github你不应不知道.很多开源组织和大神,会选择在Github这个平台上,发布他们的开源项目,学会使用Github将能够给你的学习和工作带来巨大帮助! ...
- Working with Data » 使用Visual Studio开发ASP.NET Core MVC and Entity Framework Core初学者教程
原文地址:https://docs.asp.net/en/latest/data/ef-mvc/intro.html The Contoso University sample web applica ...
随机推荐
- how to measure function performance in javascript
how to measure function performance in javascript Performance API Performance Timeline API Navigatio ...
- Flutter 获取本地图片并剪切
安装依赖 dependencies: ... image_picker: image_cropper android\app\src\main\AndroidManifest.xml 将UCropAc ...
- NGK的发行量是多少?NGK销毁机制是怎么样的?
代币销毁(Coin Burning),是指将代币从流通中永久性去除.换句话说,被销毁的代币相当于被永久性冻结,再也无法流入市场.那为什么要进行代币销毁呢? 销毁加密货币,可以使剩余加密货币的价值升高, ...
- 金三银四助力面试-手把手轻松读懂HashMap源码
前言 HashMap 对每一个学习 Java 的人来说熟悉的不能再熟悉了,然而就是这么一个熟悉的东西,真正深入到源码层面却有许多值的学习和思考的地方,现在就让我们一起来探索一下 HashMap 的源码 ...
- django学习-19.admin管理后台的配置和登录
目录结构 1.前言 2.admin管理后台的配置和登录的完整操作流程 2.1.第一步: 在[settings.py]里对常量[INSTALLED_APPS]的值进行相关配置 2.2.第二步: 在[ur ...
- 1107 Social Clusters——PAT甲级真题
1107 Social Clusters When register on a social network, you are always asked to specify your hobbies ...
- 微信小程序:单选框radio和复选框CheckBox
单选框radio: 可以通过color属性来修改颜色. 复选框checkbox:
- Java 搭建 RabbitMq 消息中间件
前言 当系统中出现"生产"和"消费"的速度或稳定性等因素不一致的时候,就需要消息队列. 名词 exchange: 交换机 routingkey: 路由key q ...
- Vue框架简介及简单使用
目录 一.前端框架介绍 二.vue框架简介 三.vue使用初体验 1. vue如何在页面中引入 2. 插值表达式 3. 文本指令 4. 方法指令(事件指令) 5. 属性指令 四.js数据类型补充 1. ...
- 看完我的笔记不懂也会懂----git
Git学习笔记 - 什么是Git - 首次使用Git - DOS常用命令 - Git常用命令 - 关于HEAD - 版本回退 - 工作区.暂存区与版本库 - git追踪的是修改而非文件本身 - 撤销修 ...