OMNeT++教程——TicToc3.2通过一个建模&仿真实例,介绍OMNeT++的一些通用特色。本教程使用的Tictoc实例,位于在OMNeT++安装目录中samples/tictoc子目录中。但是一步步按此教程学习,你将收获颇多。注意:假定你的系统已经正确安装了OMNeT++。并且你熟悉C++语言及其开发过程(编辑源程序,编译,调试等)。例子中的源程序相关调用请参考OMNeT++API文档。本文及TicToc模型改自AhmetSekercioglu(Monash大学)的TicToc教程.目录•1.两节点乒乓网络仿真•2.两节点TicToc增强模型•3.真实化模型•4.统计•5.矢量&标量结果可视化1.两节点乒乓网络仿真Setp1:两节点乒乓网络仿真作为入门级例子,我们先仿真一个两节点(tic和toc)简单网络。节点tic首先产生一个包,然后将此包在两个节点间来回转发。1.建立tictoc工作目录,进入此目录。2.建立网络拓扑文件tictoc1.ned(文本文件)simpleTxc1//简单模块类型说明gates:in:in;out:out;endsimplemoduleTictoc1//复合模块类型说明submodules://字模块列表tic:Txc1;//节点tictoc:Txc1;//节点tocconnections://两个节点间的连接定义tic.out--delay100ms--toc.in;tic.in--delay100ms--toc.out;endmodulenetworktictoc1:Tictoc1//网络定义,可见网络就是复合模块类型Tictoc1的一个变量(实例)endnetwork应该注意先定义后使用原则。其含义最好从下向上倒着看:•(network..endnetwork)定义了一个网络tictoc1(仿真的对象);•(module..endmodule)定义了一个复合模块(类型)Tictoc1,其中包含子模块tic和toc,它们都是简单模块类型Txc1的实例。Tic的输出门(out)连接到toc的输入门(in),Toc的输出门(out)连接到tic的输入门(in),传输延迟均为100ms;•(simple..endsimple)定义了一个简单模块(类型)Txc1。3.简单模块(类型)是NED描述的基本单位,其算法需要C++语言实现。简单模块(类型)Txc1的算法实现源文件txc1.cc如下:#includestring.h#includeomnetpp.hclassTxc1:publiccSimpleModule//简单模块在C++源文件中表现为一个cSimpleModule派生类。{protected:virtualvoidinitialize();virtualvoidhandleMessage(cMessage*msg);};Define_Module(Txc1);//简单模块在OMNeT++中的注册宏voidTxc1::initialize(){//仿真初始化,由节点tic发出第一条消息if(strcmp(tic,name())==0){//创建并从输出门out发出第一条消息tictocMsg,其消息内容这里并不关心.cMessage*msg=newcMessage(tictocMsg);send(msg,out);}}voidTxc1::handleMessage(cMessage*msg){//模块中一旦有消息到达,即可调用此函数进行相关处理send(msg,out);//转发消息}根据NED文件中定义的字模块关系,initialize()函数中节点tic从输出门“out”发出的消息经过100ms传输延迟必然到达节点toc的输入门“tic”,并触发其handleMessage()函数。不难看出该消息就像一只乒乓球,将在两个节点间来回传输。在OMNeT++中,仿真概念中的消息和事件都表示为cMessage对象。4.使用opp_makemake命令创建Makefile文件。Windows+MSVC环境用户使用opp_nmakemake命令创建Makefile.vc文件。5.使用make命令编译。Windows+MSVC环境用户使用使用nmake–fMakefile.vc命令编译。6.创建配置文件omnetpp.ini。该文件可以向模型中传递参数。[General]network=tictoc17.运行tictoc(文件名缺省为目录名)进行仿真8.选定仿真的网络实例名为tictoc1,进入界面后,单击工具条中Run按钮开始仿真。主窗口显示的仿真时间是虚拟时间,和程序实际运行时间无关。注意节点处理消息的仿真时间长度为0,仿真时间开销在消息传输的延迟上。9.你可以调整仿真动画的速度。其它控制如F8(停)、F4(单步)、F5(开动画)、F6(关动画)、F7(加快)等。参考源文件:tictoc1.ned,txc1.cc,omnetpp.ini【返回】【目录】2.两节点TicToc增强模型Step2:美化图示,增加调试输出在NED文件中使用display描述子句美化节点图示。注意i标签的含义。submodules:tic:Txc2;display:i=block/process,cyan;//Notei=icon,colortoc:Txc2;display:i=block/process,gold;connections:在C++文档中使用OMNeT++的ev对象输出调试信息:evSendinginitialmessage\n;//加入到initialize()函数中evReceivedmessage`msg-name()',sendingitoutagain\n;//加入到handleMessage()函数中在多模块模型中,特定模块的调试信息可以如下图操作来查看,以避免快速刷屏。参考源文件:tictoc2.ned,txc2.cc,omnetpp.iniStep3:增加状态变量这里增加一个计数器变量,实现消息交换计数。消息交换10次后被删除。classTxc3:publiccSimpleModule{private:intcounter;//增加为类成员变量protected:在initialize()函数中将counter初始化为10,并在handleMessage()函数中每发一次消息将counter减少1,当其减到0时不再转发消息。系统中事件处理完后仿真终止。WATCH(counter);//以便在图形界面Tkenv中查看counter变量双击节点tic图标,然后可看到下图示(模块窗口)。在仿真过程中,可以看到counter变量的变化。参考源文件:tictoc3.ned,txc3.cc,omnetpp.iniStep4:增加仿真参数simpleTxc4parameters:limit:numericconst;//声明了一个新参数limitgates:简单模块中的参数最终一般要进入C++代码中,如在initialize()函数中读取limit来初始化counter变量:counter=par(limit);当NED文件中模块含义参数时,可以在NED复合模块或网络定义中传值,或者通过配置文件omnetpp.ini传递参数。前者优先级高,但后者相当灵活。moduleTictoc4submodules:tic:Txc4;parameters:limit=8;//复合模块定义,子模块列表中传值display:i=block/process,cyan;toc:Txc4;display:i=block/process,gold;connections:上面子模块toc的limit参数没有赋值,需要在omnetpp.ini中进行赋值:tictoc4.toc.limit=5omnetpp.ini中支持字符通配符,所以我们都应该认识如下表示(*和**的区别在于后者还可以匹配圆点符):tictoc4.t*c.limit=5tictoc4.*.limit=5**.limit=5在图形界面Tkenv下,你可以在主窗口左边的树形结构中查看模块参数,也可以双击模块图标,在模块窗口中查看参数页面。参考源文件:tictoc4.ned,txc4.cc,omnetpp.iniStep5:模拟处理延迟之前,tic和toc立刻转发消息(仿真时长为0)。这里设它们在转发过程中将保留消息1仿真时间秒。在OMNeT++中,时间延迟(定时)可通过直接给自己发消息来实现。因此在类中增加两个cMessage指针变量:event和tictocMsg。classTxc5:publiccSimpleModule{private:cMessage*event;//定时消息cMessage*tictocMsg;//记录需转发的消息public:scheduleAt()函数负责给自己发消息,这类消息称为自消息。scheduleAt(simTime()+1.0,event);//第一参数:时间长度,单位为仿真时间秒;第二参数:需发送的消息指针)在handleMessage()函数中,不同消息需区分处理:if(msg==event)//是定时消息?也可以如下判断:if(msg-isSelfMessage())//是自消息吗?本例中去掉counter变量,以保持较少的代码。仿真图示如下:参考源文件:tictoc5.ned,txc5.cc,omnetpp.iniStep6:随机变量及参数用变量delay表示消息保留时间,并用参数delayTime来传值。参数delayTime可以引用随机变量(在omnetpp.ini中):tictoc6.tic.delayTime=exponential(3)tictoc6.toc.delayTime=truncnormal(3,1)在handleMessage()函数中引用参数:doubledelay=par(delayTime);//每次得到的值都不同evMessagearrived,startingtowaitdelaysecs...\n;tictocMsg=msg;scheduleAt(simTime()+delay,event);另外,可以如下设置丢包率:if(uniform(0,1)0.1){ev\Losing\message\n;deletemsg;}虽然引入了随机变量,但相同代码的模型多次运行,得到的结果完全相同,这一特性(可再现)对于仿真是非常重要的。OMNeT++使用确定随机数生成算法(缺省为MersenneTwisterRNG)和相同的种子。在omnetpp.ini中可以设置种子:[General]seed-0-mt=532569#或者其它任意32位数据OMNeT++支持多种RNG。这里使用RNG0。参考源文件:tictoc6.ned,txc6.cc,omnetpp.iniStep7:超时处理及中止定时器为离网络协议仿真更近一步,我们将模型改为停-等仿真,并设tic和toc分属不同的简单模块类型。toc依非0概率丢包,因此为维持仿真,tic需要补发包。下面是toc代码:voidToc7::handleMessage(cMessage*msg){if(uniform(0,1)0.1){ev\Losing\message.\n;bubble(messagelost);//动画式注释函数,参加下图deletemsg;}elseTic在发送消息是设置一个定时器,在接收消息时,取消该定时器。如果定时器在被取消之前超时(定时长度设置合理,可以认为上一个消息丢失了),tic就补发一个消息。scheduleAt(simTime()+timeout,timeoutEvent);//设置定时器cancelEvent(timeoutEvent);//取消定时器参考源文件:tictoc7.ned,txc7.cc,omnetpp.iniStep8: