最近需要学习omnet这个软件,先从例程开始,记录一下自己的学习过程和一些疑惑的地方,如果有错误的地方,请大家批评指正。也欢迎大家给我解惑,谢谢!(好多对实例的理解是借助网上的帖子)

完整地运行一个OMNeT++仿真程序,需要有.ned、.cc、.ini三个文件,分别表示网络的拓扑结构、运行程序(C++)和网络的运行入口。

下面的部分以tictoc的18个简单实例学习为主。

Tictoc 1

实现了基本的tic和toc 互相发送消息的功能。包含了基本的消息发送方法。

打开tictoc1.ned、txc1.cc。在tictoc1.ned中,可以看到网络的拓扑结构,在点击左下角source后可以看到用NED语言编写的代码;

simple Txc1
{gates:input in;output out;
}

代码中,simple定义了一个简单模块Txc1,该模块包括一个输入门in和一个输出门out。

network Tictoc1
{@display("bgb=252,190");submodules:tic: Txc1;toc: Txc1 {@display("p=114,61");}connections:tic.out --> {  delay = 100ms; } --> toc.in;tic.in <-- {  delay = 100ms; } <-- toc.out;
}

定义了名为Tictoc1的网络,网络包括两个子模块tic与toc(继承自Txc1),connections定义了两个模块之间的连接:tic的out门连接到toc的in门,tic的in门连接到toc的out门;中间加了信道,传输延迟为100ms;

在txc1.cc中,定义了网络之间运行的信息传输以及消息处理方法,代码如下:

using namespace omnetpp;
//Txc1类继承cSimpleModule
class Txc1 : public cSimpleModule
{protected:
// 重写初始化函数以及消息处理函数virtual void initialize() override;virtual void handleMessage(cMessage *msg) override;
};// The module class needs to be registered with OMNeT++
//所有模块实现时,必须添加Define_Module(xxx)
Define_Module(Txc1);void Txc1::initialize()
{
// Am I Tic or Toc?
//getName()是获取当前实例的名称,也就是NED中模块实例的名称if (strcmp("tic", getName()) == 0) {//定义消息,字符串tictocMsg为消息的名称cMessage *msg = new cMessage("tictocMsg");//发送消息,从out门发送send(msg, "out");}
}void Txc1::handleMessage(cMessage *msg)
{send(msg, "out"); // send out the message
}

using namespace是使用名字空间、strcmp是字符串比较函数,若两个字符串相等,则输出0。其中initialize和handleMessage两个函数分别是初始化和消息处理。Define_Module()是对类和节点进行注册,

右键Run as .ini文件进入仿真界面;点击run即可运行。若要单步运行,可以点击左侧的STEP;若要快速运行,可以点击FAST。结束仿真点击STOP;

Tictoc 2

实现的模块的显示@display

(其中,p:位置 b:形状大小 i:图形 is:图形大小 i2: 小图标 r:显示半径 t:显示文本 tt: 提示)

实现日志的打印输出

(omnet++自带的打印EV)

EV就相当于C++中的cout,在控制台输出,便于调试,例如可以打印某个变量值(如定时器等);注:也可以使用cout,用法如下std::cout << “test”<<std::endl,区别就是使用cout的输出是在工作台,EV输出在仿真界面;

EV << "Sending initial message\n";EV << "Received message `" << msg->getName() << "', sending it out again\n";

msg->getName()

因为msg是一个类指针,指向的是cMessage类,所以它可以使用该类gerName函数,并且使用方法为 类指针->函数名

在ned文件中使用@display,对图标进行了美化。

@display("i=,cyan"); 使得方框变为天蓝色。

@display("i=,gold"); 使得方框变为金色 。

在ned界面对图标右键,选择属性,点击Images的...可以更换图标样式;

Tictoc 3

WATCH():观察变量当前值的一个变化;增加watch之后,在仿真界面双击模块,就可以看到这个变量的实时值

实现消息的删除:在类内定义私有变量 counter 和WATCH() 的用法,逻辑为:每次收到消息,counter减1,减到0时删除消息;

handlemessage里面的getName()函数直接得到了当前收到消息的模块的名字

网络事件的结束:在这里停止的方法是delete msg,还有一种停止仿真的方法:endSimulation();

如下图所示,可以在箭头处所指地方观察counter的值的变化:

Tictoc 4

NED模块参数

在ned文件中可以给参数赋初值,如下图:

也可以在ini文件中赋初始值,如下图:

counter = par("limit");

par函数就是读取子模块参数的内容。

那么应这样使用par函数:this->getParentModule()->par("init");

例如par(“limit”)的意思就是读取limit参数的内容。par("sendMsgOnInit").boolValue()就是读取这个布尔类型参数的内容。其中有boolValue longValue stringValue xmlValue。

if (par("sendMsgOnInit").boolValue() == true) {EV << "Sending initial message\n";cMessage *msg = new cMessage("tictocMsg");send(msg, "out");}

在NED文件中例化的时候,通过修改true和false的值可以决定谁先发送,而之前的 if (strcmp("tic", getName()) == 0) 就意味让tic先发送,而现在改为if (par("sendMsgOnInit").boolValue() == true) ,意味着要根据sendMsgOnInit值决定谁先发送。

Tictoc 5

在TIC4的基础上,TXC4,是一个类定义两个对象

TIC5 采用的是在txc5的基础上分别扩展了两个类,而每个类定义一个对象;

Tictoc 6

自消息

新增加的event和tictocMeg属性分别用于自发送消息和发送消息。在文件中,自发送消息,类似于定时的功能,代码如下:

 if (strcmp("tic", getName()) == 0) {// We don't start right away, but instead send an message to ourselves// (a "self-message") -- we'll do the first sending when it arrives// back to us, at t=5.0s simulated time.EV << "Scheduling first send to t=5.0s\n";tictocMsg = new cMessage("tictocMsg");
//相当于定时器,也相当于自己给自己发送消息scheduleAt(5.0, event);
}

scheduleAt()有两个参数:指定的时间和消息,调用这个函数之后,在指定时间,处理消息模块会收到消息;simTime(),返回当前仿真时间;

在initialize函数中,tic节点在5.0s时对自己发送一条消息event。在处理消息函数handleMessage中,若收到的消息是event时,将tictocMsg发出;

Tictoc 7

NED参数定义

NED中exponential(3s),truncnormal(3s,1s)函数

simple Txc7
{
parameters:volatile double delayTime @unit(s);   // delay before sending back message@display("i=block/routing");gates:input in;output out;
}

在编写.ned文件时,为网络节点类型增加了 delayTime参数,用于表证从接收到消息到消息转发的延时。

delayTime具体数值通过.ini产生,方式包括平均分布(不确定是平均分布)和正态分布。

if (uniform(0, 1) < 0.1) {EV << "\"Losing\" message\n";delete msg;}

以上意味着有0.1的概率丢失消息,intuniform(a,b)是产生整数随机数,不加int是浮点数;

整个运行就是首先延迟5秒发,收到后延迟随机时间回发,再收到后延迟随机时间发,并且期间还有一定概率数据丢失。

Tictoc 8

丢包消息处理

定时判断消息是否到达,若没有到达则创建消息。

分别定义了tic和toc网络节点类型,因此在.cc文件中对其进行分别定义和注册。然后对tic节点结合自发送消息实现了定时重播的功能。在初始阶段发出消息的同时在1s后给自己发送一个消息,若在这之前收到过消息则取消自发送并再发送一个自发送消息;若没有收到则在1s后会收到自发送消息,此时再进行消息发送和自发送消息,达到超时重传的目的。

整体流程:

TIC先发出信息,并且等待timeout。如果timeout后收到了timeoutEvent(说明超时),则会新建一个消息再发送一次。如果timeout时间内收到了非自信息,就说明成功发送,此时取消定时并且新建一个信息发送过去。

TOC这边就是简单的接收信息,并有0.1的概率丢失。

Tictoc 9

拷贝消息的发送

实现了发送不同消息的功能。即新增加了generateNewMessage和sendCopyOf两个函数,第一个函数实现新消息的产生,第二个实现消息的发送。

void Tic9::sendCopyOf(cMessage *msg)
{// Duplicate message and send the copy.cMessage *copy = (cMessage *)msg->dup();send(copy, "out");
}

为什么要发送复制品呢?

因为消息发送出去,就意味着消息在消息队列中了。每个消息有一个唯一的ID,dup()除了ID,都会拷贝;

bubble();类似于提示,显示括号里的内容。

Tictoc 10

多模块连接

随机消息发送

节点的输入门或输出门之间连接是一一对应的;一个节点的输入门或输出门只能连接对应的输出门或输入门一次;

在tictoc10中以数组的形式实现了一个节点类型多个门以及定义多个相同的节点类型。

getIndex获取当前模块的索引,比如tic[2]的index是2;

gatesize是当前节点的门的大小。

在.cc文件中,加入了forwardMessage函数,在节点的所有输出门中,随机挑选一个进行消息发送。

Tictoc 11

channel Channel extends ned.DelayChannel {delay = 100ms;

使用channel关键字来减小代码量,拓扑结构和10相同;

ned.DelayChannel 意味延迟信道;还可以定义其他类型的信道,例如:ned.IdealChannel (理想信道无延迟);ned.DatarateChannel(可以设置数据率等)

Tictoc 12

输入输出

Inout,即是输入门也是输出门,能发送也能接受消息。

随机消息发送

gate代替in和out,Inout gate[]进一步简化代码,使用gate代替in out后,发送数据也要改变格式,send(msg, "gate$o", k); gate$o 这个o代表out,如果是i则代表in。

Tictoc 13

自定义消息

在前面的例子中,两个网络节点之间传输的信息都是系统定义的,在tictoc13中,使用了自己定义的消息类型。消息类型的定义在tictoc.msg文件中,由msg文件可以自动生成mcc和h文件,在msg文件处右键选择build即可产生_mcc文件和h文件;其中.h文件中包含了如何获取有关message的相关信息,在编写.cc文件时需要导入。

#include "tictoc13_m.h"

类型转换:(所有的消息都是继承自cMessage类)

TicTocMsg13 *ttmsg = check_and_cast<TicTocMsg13 *>(msg);

这句话的意思是,把接收到的msg类型转化为内TicTocMsg13类型。

消息中包含消息名和消息的来源和目的地,以及有它跳了几次才到达目的地的信息。

在.cc文件中,generateMessage函数使用了获取message信息的相关函数,包括设置相关参数,还使用了intuniform随机产生目的地。

//实现跳数自增
msg->setHopCount(msg->getHopCount()+1);

Tictoc 14

消息动态显示

在tictoc14中,新增了两个参数numSent和numReveived分别用于记录发送和收到的消息数目,并将其显示在仿真界面中,通过refreshDisplay()函数可以动态显示数据,在仿真过程时,系统会调用这个函数。

//进行设置显示参数
getDisplayString().setTagArg("t", 0, buf);

Tictoc 15

tictoc15在tictoc14的基础上添加了cHistogram hopCountStats;cOutVector hopCountVector;两个参数,用于记录消息在传播过程中经历的转播次数(跳数)并将其转化为统计图。

   //统计矢量hopCountVector.record(hopcount);//统计直方图hopCountStats.collect(hopcount);

最后的finish()函数是在仿真程序运行结束时,显示仿真过程的统计数据;需要重写,不重写的话,finish函数是空的;其中recordScalar是统计标量。

在.anf文件中可以查看统计数据的图。

Tictoc 16

数据统计

//定义一个信号,名字叫做arrival,类型是long
@signal[arrival](type = “long”);
@statistic[hopCount](title="hop count"; source="arrival"; record=vector,stats; interpolationmode=none);

定义一个统计量,名字叫hopCount,统计量标题名称为 hop count,数据源是arrival(和signal对应),记录形式为向量,stats代表记录了平均值,方差等,是固定形式

在.cc文件中,首先是定义了一个变量simsignal_t arrivalSignal:

class Txc16 : public cSimpleModule
{private:simsignal_t arrivalSignal;protected:virtual TicTocMsg16 *generateMessage();virtual void forwardMessage(TicTocMsg16 *msg);virtual void initialize() override;virtual void handleMessage(cMessage *msg) override;
};

并且对信号进行注册,其中括号中的参数就是统计信号的名称即.ned文件中@signal[arrival]; 每个统计信号都要注册.

 //信号注册
arrivalSignal = registerSignal("arrival");

emit(信号,数据变量),通过emit函数来对信号进行统计量的统计。

//实现跳数增加
msg->setHopCount(msg->getHopCount()+1);

在results文件夹中可以找到统计数据,可以看到统计跳数图;其中vec是矢量数据,sca是标量数据。

Tictoc 17

figure就是显示的意思,显示数据类型,位置,字体颜色等等;

figure[名称](属性);

hasGUI的意思是,是否采用界面仿真还是命令行形式进行操作;

//获得画布canvas
cCanvas *canvas = getParentModule()->getCanvas();
//通过canvas获得名称为lasthopcount的figure;
cTextFigure *textFigure = check_and_cast<cTextFigure*>(canvas->getFigure("lasthopcount"));
//设置显示文本信息,label就是通过hopcount统计, sprintf(label, "last hopCount = %d", hopcount);
textFigure->setText(label);

Tictoc 18

主要进行数据分析

在.anf文件中查看统计得到的数据,也可以将数据导出。

omnet学习记录之tictoc1-18相关推荐

  1. omnet++学习记录2

    OMNET++ 学习过程记录2 1.先在.cc中声明 class NODE1 : public cSimpleModule { } 2.再在.cc中注册 Define_Module(NODE1);写在 ...

  2. 密码库LibTomCrypt学习记录——(2.18)分组密码算法的工作模式——XTS代码

    Test_XTS_AES.h文件代码如下 #ifndef _TEST_XTS_AES_H #define _TEST_XTS_AES_H typedef unsigned __int64 ulong6 ...

  3. MMD新人学习记录博客1

    ##MMD学习记录 2019/12/18 第一次进行博客记录,不仅动画学习在探索阶段,博客的书写也同样处在摸索阶段.所以也希望能在动画学习过程中慢慢提升博客的制作水平. 当前学习MMD是通过在b站观看 ...

  4. OMNeT学习之OMNeT安装与运行

    OMNeT学习之OMNeT安装与运行 前言 本文原创,创作不易,转载请注明!!! 本人为OMNet初学者,如有错误,请不吝请教! 最近学WSN(无线传感器网络),做传感器实验,老师强调了仿真平台Mat ...

  5. OMNeT学习之新建工程

    OMNeT学习之新建工程 前言 之前学习了OMNeT的安装与运行官方的实例代码,这篇文章记录一下,OMNeT如何创建一个新的项目. 本人为初学者,如有错误望批评指正! 本文原创,创作不易,转载请注明! ...

  6. Redis的学习记录

    Redis的学习记录 1.先导了解 1.1 NOSQL概述 1.1.1 为什么要用NoSql? 1.1.2 NoSql了解 1.1.3 NoSql特点 1.1.4 NoSQL的四大分类 2. Redi ...

  7. Echarts学习记录——如何去掉网格线及网格区域颜色

    关键属性 splitLine和splitArea,可以设置相关的属性 示例代码 <!DOCTYPE html> <html lang="en"> <h ...

  8. leveldb 学习记录(四)Log文件

    前文记录 leveldb 学习记录(一) skiplist leveldb 学习记录(二) Slice leveldb 学习记录(三) MemTable 与 Immutable Memtable le ...

  9. 【转】BLE 学习记录

    原文网址:http://m.blog.csdn.net/blog/chiooo/43985401 BLE 学习记录 ANROID BLE 开发,基于 bluetoothlegatt 分析 mBluet ...

最新文章

  1. mysql语句查询今天的数据_mysql查询当天所有数据sql语句
  2. 西门子连接id_基于海创-IIoT可视化平台的西门子PLC数据采集
  3. SpringBoot - 优雅的实现【异步编程】
  4. phpcms9.6 ueditor_PHPCMS V9.6.6 修改版
  5. 线程基础知识系列(三)线程的同步
  6. python 下标越界_Python中异常处理
  7. 学习javascript语言精粹的笔记
  8. CAN笔记(15) STM32-M4 CAN通讯
  9. word vba 打开弹出msgbox,每隔10秒刷新一次域值。
  10. fastjson.JSONObject之对象与JSON转换方法
  11. Java判断奇数偶数-高效率
  12. 《统计思维-程序员数学之概率统计》学习笔记
  13. 【HeadFirst】设计模式
  14. linux安装包apr安装说明,Linux下安装Apr及其Apr-util的基本步骤
  15. c语言解除键盘锁定,解除键盘锁定,详细教您笔记本解除键盘锁定
  16. Detection with Enriched Semantics(DES)算法笔记
  17. 练习记录-用FSL工具对DTI数据进行FDT预处理
  18. arcgis.js加载geojson
  19. 计算二叉树的深度和叶子结点数
  20. ThinkCMF-上传多个图片源码解读

热门文章

  1. MyBatis-02-CRUD
  2. 爬取近千张女神赫本的美照,做成网站并给其中的黑白照片上色,好玩!
  3. 论文阅读_Same Coverage, Less Bloat: Accelerating Binary-only Fuzzing with Coverage-preserving Coverage-g
  4. 文献阅读 | Distribution of Parental Genome Blocksin Recombinant Inbred Lines
  5. Web前端教程学习笔记1.2-2022.10.17始
  6. 字节三面:对于 Spring 你了解多少?如果你会了这 150 道题 ,吊打面试官岂不是洒洒水
  7. Python爬虫——来自新人的叹息
  8. 计算机显卡性价比推荐,性能性价比兼顾!平民级显卡推荐
  9. 连面拼多多、美团、头条、快手后给大家划下重点
  10. 既生synchronized,何生volatile (synchronized与volatile的区别)