学习自:(6条消息) omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_叶局长的博客-CSDN博客
主要有3步:
File->New Project->Omnet++ Project
项目新建之后,我们可以看到src、simulation文件夹:
simulation:存放项目配置文件;我们在配置文件中指定想要模拟的网络、网络中节点的位置等
src:存放所有源代码,包括ned文件、C++源文件等;
使用omnet进行仿真,我们首先需要定义网络的拓扑结构
在src目录下,我们新建一个network,选择one item,此时我们就有了一个网络,当然现在里边什么都没有。点击Design标签,可以以GUI的形式查看ned文件当前的内容。
逻辑上,omnet++中的module相当于C++中的class,并且可以在module中定义属性,我们用module实例化出的module对象,又可以放到其他的模块中。
代码上,omnet++中的module就是C++中的class,在定义网络行为时,我们需要用到它的属性、参数等。
在omnet中,网络中的所有东西(如节点、服务器等)都以module形式定义:
一个Node、很多个Nodes、一个Network,都可以是一个Module;Network的本质上就是compound module;
一个module的定义分为3步:
定义一个simple module的语法如下:
simple Host
{
…
parameters://定义该module的参数,如传输速率等
…
gates: //定义该module的输入、输出口及个数
…
}
定义一个compound module的一般语法如下,所有的sections都是可选的:
module Host
{
types: //定义module类型(在submodules中使用),信道类型(在connections中使用)等
…
parameters://定义该moduel的参数,如传输速率、节点个数等
…
gates: //定义该module的输入和输出口以及个数
…
submodules://定义submodule实例
…
connections://定义submodule间的链接方式
…
}
对于simple module,我们继承自cSimpleModule;
对于compound module,我们继承自cModule;
我们来定义一个C++ Module类:
#include
class ExampleModule:public omnetpp::cSimpleModule{
public:
ExampleModule();
virtual ~ExampleModule();
};
Define_Module(ExampleModule);//Module与其对应class之间的联系
在类定义的后面,添加Define_Module(module名);,将ned文件中的module与指定的C++文件中的Module类联系起来
NED属性是元数据注释,这些属性可以被附加到modules、parameters、gates、connections、NED files、packages和NED中的一切虚拟事物。
@display、@class、@namespace、@unit、@prompt、@loose、@directIn都是属性,这些属性我们已经在之前的几节中说过了,但是那些例子只抓住了表面,给出的是这些属性的基本使用方法。
使用属性,我们就可以为NED属性添加额外的信息。一些属性已经被NED仿真内核给解释了;另一些属性从仿真模型中读入并使用,并且提供给NED编辑工具使用。
将这些属性添加到某个类型中,之后我们在定义每个实例时就不能使用不同的属性了。所有module、connections、parametes等实例,都是由NED文件中的特定位置创建出来的,它们都有其特有的属性。
下面是一个使用元数据注释的例子:
@namespace(foo);//文件属性
module Example
{
parameters:
@node;//module属性
@display("i=device/pc");//module属性
int a @unit(s)=default(1);//parameter属性
gates:
output out @loose @labels(pk);//gate属性
submodules:
src:Source{
parameters:
@display("p=150,100");//submodule属性
count @prompt("Enter count:");//为parameter添加一个属性
gates:
out[] @loose;//为gate添加一个属性
}
…
connections:
src.out++ -->{@display("ls=green,2");}--> sink1.in;//connection属性
src.out++ --> Channel{@display("ls=green,2");}--> sink2.in;
}
在ned文件中,我们可以定义信道,定义的一般语法如下:
channel 信道名 extends 继承的信道
{
…信道属性…
}
大多数情况下,我们不用去定义信道,oomnet++自带了三个信道ned.IdealChannel,ned.DelayChannel和ned.DatarateChannel,详细可以看:https://doc.omnetpp.org/omnetpp/manual/#sec:ned-lang:channels
我们也可以直接在connections中写出信道的属性,省去了定义信道的步骤。
定义在parameters中的属性,在配置文件.ini中指定。
omnet++根目录的sample目录下官方提供了许多例子供我们参考,这里挑选几个比较经典的例子:
先看一个RIMAC的节点,SimpleNode:
package RIMAC.simplenode;
simple SimpleNode
{
parameters:
double x @unit(m);
double y @unit(m);
double txRange @unit(m);//数据传输距离
double senRange @unit(m);//数据感知距离
double Twait @unit(s);//事件等待时间
double bitRate;//传输速率
double animationHoldTimeOnCollision @unit(s);//碰撞时动画持续时间
volatile double frameTime=uniform(0.5s,1.5s) @unit(s);//一帧的时间
double sleepTime @unit(s);//睡眠时间
double sendConsumption @unit(W);//发送功耗
double recvConsumption @unit(W);//接收功耗
double sleepConsumption @unit(W);//睡眠功耗
double idleConsumption @unit(W);//空闲功耗
double energy @unit(J);//初始能量
int packetSize @unit(B);//数据包大小
@display("p=$x,$y");
@class(RIMAC::simpleNode);
@signal[energyLeft](type="double");
@staticstic[energyLeftStat](title="energyLeft";source="energyLeft";record=vector,stats);
gates:
input in @directIn;
}
Sink定义:
package RIMAC;
import RIMAC.simplenode.SimpleNode;
simple Sink extends SimpleNode
{
parameters:
@class(RIMAC::Sink);
@display("p=$x,$y;i=device/terminal;r=$txRange");
@signal[e2etd](type="double");
@statistic[e2etdStat](title="e2etd";source="e2etd";record=vector,stats);
@signal[ae2etd](type="double");
@statistic[ae2etdStat](title="ae2etd";source="ae2etd";record=vector,stats);
}
启动仿真后,事件执行的伪代码如下:
初始化(initialize) //包括构建模型,添加初始化事件到FES中
while(FES不为空&&仿真未结束)
{
从FES中取出事件
t := 该事件发生时间
执行事件
(事件执行过程中,可能往FES中添加事件,也可能往FES中删除事件)
}
结束仿真(写入统计数据,etc.)
omnet网络的整个过程如下:
perform simulation run:
build network
(i.e. the system module and its submodules recursively)
insert starter messages for all submodules using activity()
do callInitialize() on system module
enter event loop
if (event loop terminated normally)
do callFinish() on system module
clean up
模拟运行:
构造网络
(递归构造系统module和每个module的submodule)
用activity()为所有submodule插入开始消息
在系统module中运行callInitialize():
进入事件循环
if(事件循环正常结束)
在系统mudule中运行callFinish()
清理
其中callInitialize()和callFinish()的伪代码如下:
callInitialize()
{
call to user-defined initialize() function
if (module is compound)
for (each submodule)
do callInitialize() on submodule
}
{
调用用户自定义的initialize()函数
if (module是compound module)
for(each submodule)
在每个submodule中调用callInitialize()
}
callFinish()
{
if(module is compound)
for(each submodule)
do callFinish() on submodule
call to user-defined finish() function
}
从上边的执行过程可知,module是有初始化事件的,我们通过父类cSimpleModule的initialize()方法来进行初始化。
可以重写两个方法来进行多阶段的初始化,在numInitStages中返回阶段的个数,一般来说,我们可以在第一个初始化阶段进行变量赋值等操作,后面的阶段可以进行周期计算等:
virtual void initialize(int stage);
virtual int numInitStages() const;
模块通过调用finish()来进行仿真结束的工作
消息的发送由sendXXX系列函数完成,消息的接收基本都由handleMessage完成
cMessage类是所有消息类的父类,我们可以自定义一个消息类(继承自cMesaage),也可以直接使用这个类:
cMessage(const char *name=nullptr , short kind=0)
Message sending.
virtual void send (cMessage *msg, int gateid)
virtual void send (cMessage *msg, const char *gatename, int gateindex=-1)
virtual void send (cMessage *msg, cGate *outputgate)
virtual void sendDelayed (cMessage *msg, simtime_t delay, int gateid)
virtual void sendDelayed (cMessage *msg, simtime_t delay, const char *gatename, int gateindex=-1)
virtual void sendDelayed (cMessage *msg, simtime_t delay, cGate *outputgate)
virtual void sendDirect (cMessage *msg, cModule *mod, const char *inputGateName, int gateIndex=-1)
virtual void sendDirect (cMessage *msg, cModule *mod, int inputGateId)
virtual void sendDirect (cMessage *msg, cGate *inputGate)
virtual void sendDirect (cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, const char *inputGateName, int gateIndex=-1)
virtual void sendDirect (cMessage *msg, simtime_t propagationDelay, simtime_t duration, cModule *mod, int inputGateId)
virtual void sendDirect (cMessage *msg, simtime_t propagationDelay, simtime_t duration, cGate *inputGate)
手机扫一扫
移动阅读更方便
你可能感兴趣的文章