omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程

文章目录

  • omnet
    • 1 网络仿真软件综述
      • 01 wsn仿真软件
      • 02 为什么使用omnet
      • 03 学习资料
      • 04 目标
    • 2 omnet介绍
      • 1 omnet安装与启动
      • 2 使用omnet仿真的一般步骤
      • 3 新建项目
    • 3 定义仿真网络的拓扑结构
      • 01 新建一个空的 network
      • 02 Module的概念
        • 01-Module的概念
        • 02-Module Type的定义步骤
          • 1. ned文件中定义
          • 2. C++文件定义
          • 3. 将C++文件与ned文件联系起来
        • 03-元数据注释 (属性)
        • 04-Channel(信道)
        • 05-配置文件
      • 03 几个例子
        • 01 AHOLA
        • 02 tictoc
        • 03 SimpleNode 和 Sink
    • 4 控制网络仿真时的行为
      • 01 omnet仿真原理
        • 01-离散事件模拟
        • 02-omnet事件循环
      • 02 网络的初始化和结束原理
        • 01-模块的初始化
        • 02-模块的多阶段初始化
        • 03-模块的结束
      • 03 消息的发送与接收
        • 1. 默认的消息cMessage类
        • 1. sendXXX(-)
        • 2. handleMessage(Msg *)
        • 3. ScheduelAt() 自消息的发送
    • 例子阅读
      • 官方 19 个 tictoc
    • 仿真主要参考的资料
    • 5 状态的定义(如果有时间的话)
      • 01 睡眠实现

omnet

具体实现官方有很多, 主要是一些概念比较不太好懂

1 网络仿真软件综述

01 wsn仿真软件

看博客: wsn simulator

02 为什么使用omnet

  1. 简单易用
  2. 提供强大的GUI
  3. 有支持团队不断在更新维护

03 学习资料

omnet++:https://omnetpp.org/documentation/
C++: CPrimer 中文版

04 目标

  1. 讲omnet的基本使用
    1. 使用ned进行仿真网络结构的定义
    2. omnet中模块的概念
  2. 从头带大家实现一个有线的tictoc 和 一个无线的tictoc

2 omnet介绍

1 omnet安装与启动

  1. 安装必须进行的步骤
    1. 下载OMNeT : 下载地址
    2. 将存档解压缩到新文件夹中。
    3. 打开mingw.cmd 键入./configure和后make (这步可能要30分钟左右)
    4. 将path/to/OMNeT/build添加path/to/OMNeT/build目录到PATH环境变量中。
    5. 输入omnetpp确保安装正常。预计OMNeT ++开发环境将启动。

注: (原则上不需要下载任何东西, 都是包括在安装包中的, 包括Qt环境,编译器mingw等)
有关更多安装说明, 请访问omnet installGuide。

  1. 安装完成后, 打开mingwenv.cmd, 输出omnetpp, 即可打开omnetIDE
    omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第1张图片
  2. 选择工作目录, 打开后界面如下所示
    omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第2张图片

2 使用omnet仿真的一般步骤

使用omnet仿真

主要有三步:

  1. 使用ned(network description)定义网络拓扑结构
  2. 利用C++编写实现网络的各种行为
  3. 编写配置文件指定网络参数, 利用配置文件启动项目

3 新建项目

File->New-Project->Omnet++Project 来新建项目, 项目新建后, 我们可以看到src, simulation文件夹

  • simulation: 存放项目配置文件

    我们在配置文件中指定想模拟的网络, 网络中节点的位置等

  • src: 存放所有源代码, 包括ned文件, C++源文件等

关于所有文件夹的作用看: https://doc.omnetpp.org/omnetpp/manual/#cha:ned-lang

3 定义仿真网络的拓扑结构

使用omnet进行仿真, 我们首先需要去定义网络的拓扑结构

01 新建一个空的 network

src目录下, 我们新建一个network , 选择one item , 此时我们就有了一个网络,当然现在里面什么也没有, 点击Design标签, 可以以GUI的形式查看ned文件当前的内容

02 Module的概念

01-Module的概念

逻辑上, omnet++中的module就相当于C++中的类,并且在模块中可以定义属性,我们用module实例化出来的模块对象, 又可以放到其他的模块中

代码上, omnet++中的module最终就是一个C++中的类,在定义网络的行为时, 我们需要用到他的属性,参数等等

  1. 在omnet中, 网络中的所有东西(如一个节点, 服务器等)都以module形式定义
  • 最低层的模块称为 简单模块(simple Module)
  • 模块可以添加到复合模块(compound module)
  • 模块之间可以相互嵌套, 嵌套的层级没有限制
  • 模块之间可以定义继承关系

一个节点, 很多个节点, 一块网络, 都可以是一个模块
network本质上就是一个复合模块

omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第3张图片

02-Module Type的定义步骤

一个模块的定义分为3个步骤

  1. 在ned文件中定义
  2. 使用C++继承omnet的cModule类cSimpleModule类, 定义一个Module类
  3. 将ned文件中定义的Module与C++中定义的Module联系起来
1. ned文件中定义

定义一个复合模块的一般语法如下, 所有的sections都为可选的

module Host
{
   types:  //定义模块类型(在submodules中使用),信道类型(在connections中使用)等
       ...
   parameters:  //定义该模块的参数, 如传输速率,节点个数等
       ...
   gates:   // 定义该模块的输入和输出口及个数
       ...
   submodules: // 定义子模块实例
       ...
   connections: // 定义子模块间的链接方式
       ...
}

定义一个简单模块的语法如下:

simple Host
{
       ...
   parameters:  //定义该模块的参数, 如传输速率等
       ...
   gates:   // 定义该模块的输入和输出口及个数
       ...
  }
2. C++文件定义

对于简单模块我们继承cSimpleModule
对于复合模块我们继承cModule类, 来定义一个C++ Module类

#include 

class ExampleModule: public omnetpp::cSimpleModule {
public:
    ExampleModule();
    virtual ~ExampleModule();
};

Define_Module(ExampleModule);
3. 将C++文件与ned文件联系起来

在类定义的后面, 添加Define_Module(模块名);, 将模块与指定的C++类联系起来

#include 

class ExampleModule: public omnetpp::cSimpleModule {
public:
    ExampleModule();
    virtual ~ExampleModule();
};

Define_Module(ExampleModule);

03-元数据注释 (属性)

NED properties are metadata annotations that can be added to modules, parameters, gates, connections, NED files, packages, and virtually anything in NED. @display, @class, @namespace, @unit, @prompt, @loose, @directIn are all properties that have been mentioned in previous sections, but those examples only scratch the surface of what properties are used for.

Using properties, one can attach extra information to NED elements. Some properties are interpreted by NED, by the simulation kernel; other properties may be read and used from within the simulation model, or provide hints for NED editing tools.

Properties are attached to the type, so one cannot have different properties defined per-instance. All instances of modules, connections, parameters, etc. created from any particular location in the NED files have identical properties.

下面是一个使用元数据注解的例子

@namespace(foo);  // file property

module Example
{
    parameters:
       @node;   // module property
       @display("i=device/pc");   // module property
       int a @unit(s) = default(1); // parameter property
    gates:
       output out @loose @labels(pk);  // gate properties
    submodules:
       src: Source {
           parameters:
              @display("p=150,100");  // submodule property
              count @prompt("Enter count:"); // adding a property to a parameter
           gates:
              out[] @loose;  // adding a property to a gate
       }
       ...
    connections:
       src.out++ --> { @display("ls=green,2"); } --> sink1.in; // connection prop.
       src.out++ --> Channel { @display("ls=green,2"); } --> sink2.in;
}

04-Channel(信道)

在ned文件中, 我们可以定义信道, 定义的一般语法如下

channel 信道名 extends 要继承的信道   // requires a CustomChannel C++ class
{
...信道属性...
}

大多数情况下我们不用去定义信道, omnet++自带了三个信道ned.IdealChannel, ned.DelayChannelned.DatarateChannel
详细请看:https://doc.omnetpp.org/omnetpp/manual/#sec:ned-lang:channels

我们也可以直接在connections中直接写出信道的属性, 省去了定义信道的步骤
在定义不同

05-配置文件

定义在parameters 中的属性, 在配置文件.ini中指定

03 几个例子

omnet++根目录的sample目录下官方提供了许多例子供我们参考, 这里挑选几个较为典型的例子

01 AHOLA

02 tictoc

03 SimpleNode 和 Sink

我们先来看一个模块, 这是我做RIMAC时定义的一个节点, SimpleNode

//Simple Node 模块
//定义普通节点拥有的参数
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");
    	@statistic[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);

}

4 控制网络仿真时的行为

01 omnet仿真原理

01-离散事件模拟

  1. 离散事件系统(Discrete Event System)是指事件发生在时间线中离散的部分, 对于计算机网络而言正像是如此

  2. 离散事件模拟系统通过在称为FES (Future Event Set) or FEL (Future Event List) 的 数据结构中保存未来事件的集合来实现

  3. omnet++底层使用了 二叉堆实现的优先级队列事件循环(Eventloop) 来实现了这一套模拟机制
    omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第4张图片

02-omnet事件循环

启动仿真后, 事件执行的伪代码如下

初始化(initialize) -- 包括构建模型,添加初始化事件到FES中

while (FES不为空 && 仿真未结束)
{
    从FES中取出事件
    t := 该事件发生时间
    执行事件
    (事件执行过程中,可能往FES中添加事件, 也可能往FES中删除事件)
}
结束仿真 (写入统计数据, etc.)

02 网络的初始化和结束原理

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 // (described earlier)
    if (event loop terminated normally) // i.e. no errors
        do callFinish() on system module
    clean up

callInitialize和callFinish的伪代码如下


callInitialize()
{
    call to user-defined initialize() function
    if (module is compound)
        for (each submodule)
            do callInitialize() on submodule
}

callFinish()
{
    if (module is compound)
        for (each submodule)
            do callFinish() on submodule
    call to user-defined finish() function
}

01-模块的初始化

从上面的执行过程可知, 模块是有初始化事件的, 我们通过父类cSimpleModuleinitialize()方法来进行初始化,

1.window–>
2.preferrence–>
3.general–>
4.keys–>
来添加重载快捷键
omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第5张图片

模块调试:
EV<<“initialize!!!”<<"("<

02-模块的多阶段初始化

可以重写两个方法来进行多阶段的初始化,在numInitStages 中返回阶段的个数
一般来说,我们在第一个初始化阶段进行变量赋值等操作, 后面的阶段可以进行周期计算等

virtual void initialize(int stage);
virtual int numInitStages() const;

03-模块的结束

模块通过调用finish()来进行仿真结束的工作

03 消息的发送与接收

消息的发送由 sendXXX 系列函数完成, 消息的接收基本都由handleMessage完成

1. 默认的消息cMessage类

cMessage类是所有消息类的父类, 我们可以自定义一个消息类(当然必须继承cMessage类), 也可以直接使用这个类

  1. 构造函数:
    1.  cMessage (const char *name=nullptr, short kind=0) 
      

cMessage API reference

1. sendXXX(-)

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)

2. handleMessage(Msg *)

handleMessage()
在这里插入图片描述

3. ScheduelAt() 自消息的发送

scheduelAt()
omnet++ 快速入门 | 计算机网络仿真 | omnet++ 入门教程_第6张图片

例子阅读

官方 19 个 tictoc

仿真主要参考的资料

  1. 我们不知道一个函数的作用的时候, 绝大多数情况下, 都是去查cSimpleModulle
    cSimpleModule

  2. 其次会去 SimulationManual 中查, 里面会有一些实际应用的例子

5 状态的定义(如果有时间的话)

01 睡眠实现

你可能感兴趣的:(omnet,计算机网络,仿真,仿真软件,科研)