马上要创造一个真正的网络了
文档链接:https://docs.omnetpp.org/tutorials/tictoc/part4/
TicToc10使用模块向量创建了六个模块,并规划了一定的连接关系,规定每个模块收到一个消息之后会随机发送出去。
一个消息在tic[0]
创建,直到tic[3]
接收到为止。
一个缺点是消息可能在相连的两个模块之间来回发送很多次(经过测试确实经常陷入循环)
tictoc10.ned
simple Txc10
{
parameters:
@display("i=block/routing");
gates:
input in[];
output out[];
}
network Tictoc10
{
submodules:
// 用Txc来建立网络的时候,决定向量的大小
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++;
}
txc10.cc
#include
#include
#include
using namespace omnetpp;
class Txc10 : public cSimpleModule{
protected:
virtual void forwardMessage(cMessage *msg);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Txc10);
void Txc10::forwardMessage(cMessage *msg){
// gateSize获取与当前门相连门的数量
int n = gateSize("out");
// 从所有与当前门相连的门中任选一个将消息发送出去
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on port out[" << k <<"].\n";
send(msg, "out", k);
}
void Txc10::initialize(){
if(getIndex() == 0){
// Boot the process scheduling the initial message as a self-message.
char msgname[20];
sprintf(msgname, "tic-%d", getIndex());
cMessage *msg = new cMessage(msgname);
scheduleAt(0.0, msg);
}
}
void Txc10::handleMessage(cMessage *msg){
if(getIndex() == 3){
EV << "Message "<< msg << "arrived.\n";
delete msg;
}else{
EV << "tic[" << getIndex() << "] is ready to send Message.\n";
forwardMessage(msg);
}
}
一个没有解决的问题:ned文件中设计图无法显示出连接关系,只有进入运行状态才能看到连接关系,不知道这是正常状态还是有哪里没有设置正确
任务目标:与TicToc10
相同,在TicToc10
的基础简化了网络的连接部分。
TicToc11
增加了types
字段,定义了channel
类型的变量Channels
,用来指定统一的延时参数delay
。
tictoc11.ned
simple Txc11{
parameters:
@display("i=block/routing");
gates:
input in[];
output out[];
}
network Tictoc11{
types:
channel Channel extends ned.DelayChannel{
delay = 100ms;
}
submodules:
tic[6]:Txc11;
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++;
}
txc11.cc
与txc10.cc
相同
总结
channel有三种类型,分别是:
ned.IdealChannel
ned.DelayChannel
,参数delay
,disabled
(默认false,= true时丢弃通道所有消息)
ned.DatarateChannel
更多关于channel的内容参考https://doc.omnetpp.org/omnetpp/manual/#sec:ned-lang:channels
在TicToc11
的基础上将门修改成为双向门
tictoc12.ned
simple Txc12{
parameters:
@display("i=block/routing");
gates:
inout gate[]; //双向门
}
network Tictoc12{
types:
channel Channel extends ned.DelayChannel{
delay = 100ms;
}
submodules:
tic[6] : Txc12;
connections:
tic[0].gate++ <--> Channel <--> tic[1].gate++;
tic[1].gate++ <--> Channel <--> tic[2].gate++;
tic[1].gate++ <--> Channel <--> tic[4].gate++;
tic[3].gate++ <--> Channel <--> tic[4].gate++;
tic[4].gate++ <--> Channel <--> tic[5].gate++;
}
txc12.cc
只在txc10.cc
的基础上修改了以下内容,将
int n = gateSize("out");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on port out[" << k <<"].\n";
send(msg, "out", k);
修改为
// 门的名字与ned模块中相同
int n = gateSize("gate");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << " on port out[" << k <<"].\n";
// inout门使用$o和$i识别输出和输入
// 门的名称+“$o”表示输出门,门的名称+“$i”表示输入门
send(msg, "gate$o", k);
该案例主要研究自定义消息,自定义消息中包括源、目的、跳数三个参数
程序工作流程:第0个模块初始化生成一条消息,任意设置一个目的地址,向任意一个模块发送,接收到消息的模块判断是否是属于它的消息,如果是,就接收消息并销毁,再生成一条新消息继续发送;如果不是,则选择任意一个模块发送出去,直到消息的目的模块收到该消息。
tictoc13.ned
与tictoc12.ned
相同
tictoc13.msg
从cMessage
派生一个子类TicTocMsg13
,这个子类定义在tictoc13.msg
中
编译会自动生成tictoc13_m.h
和tictoc13_m.cc
两个文件,需要在C++代码中调用tictoc13_m.h
// 该子类包含三个变量,源、目的和跳数
message TicTocMsg13{
int source;
int destination;
int hopCount = 0;
}
txc13.cc
#include
#include
#include
using namespace omnetpp;
// 引用头文件,tictoc13.msg编译后自动生成
#include "tictoc13_m.h"
class Txc13 : public cSimpleModule{
protected:
virtual TicTocMsg13 *generateMessage(); //消息生成函数
virtual void forwardMessage(TicTocMsg13 *msg); //消息转发函数
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Txc13);
void Txc13::initialize(){
// 模块0发送第一条消息
if(getIndex() == 0){
TicTocMsg13 *msg = generateMessage();
// 将初始消息调度为自消息
scheduleAt(0.0, msg);
}
}
void Txc13::handleMessage(cMessage *msg){
// 强制类型转换,将收到的的cMessage类的消息转换成TicTocMsg13
TicTocMsg13 *ttmsg = check_and_cast<TicTocMsg13 *>(msg);
// 消息的目的地址是当前模块,证明消息到达
if (ttmsg->getDestination() == getIndex()) {
// Message arrived.
EV << "Message " << ttmsg << " arrived after " << ttmsg->getHopCount() << " hops.\n";
bubble("ARRIVED, starting new one!");
delete ttmsg;
// Generate another one.
EV << "Generating another message: ";
TicTocMsg13 *newmsg = generateMessage();
EV << newmsg << endl;
forwardMessage(newmsg);
}
else {
// We need to forward the message.
// 这个消息目的地址不是该端口,需要再转发出去
forwardMessage(ttmsg);
}
}
TicTocMsg13 *Txc13::generateMessage(){
int src = getIndex(); // 源地址是当前模块索引号
int n = getVectorSize(); // 获取门向量的长度 6
int dest = intuniform(0, n-2); // 目的地址不包括它自己
if(dest >= src) dest++;
char msgname[20];
sprintf(msgname, "tic-%d-to-%d", src, dest);
TicTocMsg13 *msg = new TicTocMsg13(msgname);
msg->setSource(src);
msg->setDestination(dest);
return msg;
}
void Txc13::forwardMessage(TicTocMsg13 *msg){
msg->setHopCount(msg->getHopCount()+1);
int n = gateSize("gate");
int k = intuniform(0, n-1);
EV << "Forwarding message " << msg << "on gage[" << k << " ].\n";
send(msg, "gate$o", k);
}
消息往往需要经过很多跳才能从源转发到目的模块。