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.nedtxc10.ccomnetpp.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.nedtxc11.ccomnetpp.ini

4.3使用双向连接

如果再检查一下该connections部分,我们将意识到每个节点对都通过两个连接连接。每个方向一个。OMNeT ++ 4支持两种方式的连接,因此让我们使用它们。

首先,我们必须定义双向(或所谓的inout)门,而不是之前使用的分离inputoutput门。

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.nedtxc12.ccomnetpp.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.htictoc13_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.nedtictoc13.msgtxc13.ccomnetpp.ini

练习

在此模型中,在任何给定时刻只有一条消息正在运行:节点仅在另一条消息到达它们时才生成一条消息。我们这样做是为了使跟踪仿真变得更加容易。更改模块类,以便改为定期生成消息。消息之间的间隔应该是一个模块参数,返回指数分布的随机数。

Oment++ 初学者教程 第4节-将其转变为真实网络的更多相关文章

  1. Go GraphQL初学者教程

    Go GraphQL初学者教程 https://tutorialedge.net/golang/go-graphql-beginners-tutorial/ https://tutorialedge. ...

  2. MapServer Tutorial——MapServer7.2.1教程学习——第一节:MapServer的基本配置管理,静态地图应用以及MapFile文件

    MapServer Tutorial——MapServer7.2.1教程学习——第一节:MapServer的基本配置管理,静态地图应用以及MapFile文件 前言 万事开头难,有了<MapSer ...

  3. Easyui + asp.net MVC 系列教程 第19-23 节 完成注销 登录限制过滤 添加用户

    前面视频 文章地址 Easyui + asp.net MVC 系列教程 第09-17 节 完成登录 高清录制  Easyui + asp.net mvc + sqlite 开发教程(录屏)适合入门  ...

  4. 《SLAM for Dummies》中文版《SLAM初学者教程》

    SLAM for Dummies  SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping  一本关于实时定位及绘图 ...

  5. SLAM for Dummies SLAM初学者教程 中文翻译 1到4章

    SLAM for Dummies  SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping  一本关于实时定位及绘图 ...

  6. PANDAS 数据分析初学者教程

    Pandas 初学者教程       2018-05-19 六尺巷人 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非常重要的Python包.它不仅提供了很多方法,使得数据处理非常 ...

  7. OMnet++ 初学者教程 第一节 入门

    第1部分-入门 1.1模型 首先,让我们从一个包含两个节点的"network"开始.节点将做一些简单的事情:一个是节点将创建一个数据包,而两个节点将继续来回传递相同的数据包.我们将 ...

  8. Github初学者教程(一)

    如果你是一名程序员,或者是相关专业的学生,那么Github你不应不知道.很多开源组织和大神,会选择在Github这个平台上,发布他们的开源项目,学会使用Github将能够给你的学习和工作带来巨大帮助! ...

  9. 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 ...

随机推荐

  1. how to measure function performance in javascript

    how to measure function performance in javascript Performance API Performance Timeline API Navigatio ...

  2. Flutter 获取本地图片并剪切

    安装依赖 dependencies: ... image_picker: image_cropper android\app\src\main\AndroidManifest.xml 将UCropAc ...

  3. NGK的发行量是多少?NGK销毁机制是怎么样的?

    代币销毁(Coin Burning),是指将代币从流通中永久性去除.换句话说,被销毁的代币相当于被永久性冻结,再也无法流入市场.那为什么要进行代币销毁呢? 销毁加密货币,可以使剩余加密货币的价值升高, ...

  4. 金三银四助力面试-手把手轻松读懂HashMap源码

    前言 HashMap 对每一个学习 Java 的人来说熟悉的不能再熟悉了,然而就是这么一个熟悉的东西,真正深入到源码层面却有许多值的学习和思考的地方,现在就让我们一起来探索一下 HashMap 的源码 ...

  5. django学习-19.admin管理后台的配置和登录

    目录结构 1.前言 2.admin管理后台的配置和登录的完整操作流程 2.1.第一步: 在[settings.py]里对常量[INSTALLED_APPS]的值进行相关配置 2.2.第二步: 在[ur ...

  6. 1107 Social Clusters——PAT甲级真题

    1107 Social Clusters When register on a social network, you are always asked to specify your hobbies ...

  7. 微信小程序:单选框radio和复选框CheckBox

    单选框radio: 可以通过color属性来修改颜色. 复选框checkbox:

  8. Java 搭建 RabbitMq 消息中间件

    前言 当系统中出现"生产"和"消费"的速度或稳定性等因素不一致的时候,就需要消息队列. 名词 exchange: 交换机 routingkey: 路由key q ...

  9. Vue框架简介及简单使用

    目录 一.前端框架介绍 二.vue框架简介 三.vue使用初体验 1. vue如何在页面中引入 2. 插值表达式 3. 文本指令 4. 方法指令(事件指令) 5. 属性指令 四.js数据类型补充 1. ...

  10. 看完我的笔记不懂也会懂----git

    Git学习笔记 - 什么是Git - 首次使用Git - DOS常用命令 - Git常用命令 - 关于HEAD - 版本回退 - 工作区.暂存区与版本库 - git追踪的是修改而非文件本身 - 撤销修 ...