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. flutter package & pub publish

    flutter package & pub publish dart-library-package https://pub.dev/packages/dart_library_package ...

  2. Full Stack Web Development

    Full Stack Web Development Web Stacks MEAN (Mongo, Express, Angular and Node) LAMP (Linux, Apache, M ...

  3. vue & npm & components & plugins

    vue & npm & components & plugins how to publish an vue ui component to npm? https://www. ...

  4. 未来,Baccarat将如何拓展生态版图?

    Baccarat最近几度冲上DeFi版面的热搜,一是因为BGV价格不断的上涨,二是因为生态建设者的不断涌入.可以说,当下的Baccarat,实在是太火爆了.那么在未来,Baccarat还将会持续火爆吗 ...

  5. APC体育公司重视“女性经济 ”深度挖掘女性市场

    据消费者追踪服务调查数据显示,从2020年1月到8月,a private company体育公司(公司编号:08703733)品牌下的女性运动服装的在线销售额较上一年增长了77%. 女性市场已然成为A ...

  6. Mila Fletcher :其实高度自律的人生并没有那么难养成

    在日常生活中,我们经常会发现,不论是学习,考证,工作,都需要坚持付出.但是很多人都没有办法在枯燥的学习过程中持续下去,这通常是因为不够自律导致的.但是尽管大家都知道自律是多么重要,却没有几个人可以真正 ...

  7. 教你玩转CSS border(边框)

    边框样式 边框样式属性指定要显示什么样的边界. border-style属性用来定义边框的样式 border-style的值 代码演示: <!DOCTYPE html> <html ...

  8. Java中print、printf、println的区别

    Java中print.printf.println的区别 区别 print:标准输出,但不换行,不可以空参: println:标准输出,但会自动换行,可以空参,可以看做:println()相当于pri ...

  9. C++算法代码——n的全排列/全排列问题

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1541 题目描述 输入一个整数n,输出的n(n<=100)的全排列. 输入 输入 ...

  10. glibc内存管理那些事儿

    本文转载自glibc内存管理那些事儿 Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: 进程虚拟地址空间分布 图中,0xC0000000开始的最高1G空间是内核地址空间,剩下 ...