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

article/2025/7/20 21:28:09

文章目录

  • 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
    在这里插入图片描述
  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本质上就是一个复合模块

在这里插入图片描述

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 <omnetpp/csimplemodule.h>class ExampleModule: public omnetpp::cSimpleModule {
public:ExampleModule();virtual ~ExampleModule();
};Define_Module(ExampleModule);
3. 将C++文件与ned文件联系起来

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

#include <omnetpp/csimplemodule.h>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 propertymodule Example
{parameters:@node;   // module property@display("i=device/pc");   // module propertyint a @unit(s) = default(1); // parameter propertygates:output out @loose @labels(pk);  // gate propertiessubmodules:src: Source {parameters:@display("p=150,100");  // submodule propertycount @prompt("Enter count:"); // adding a property to a parametergates: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) 来实现了这一套模拟机制
    在这里插入图片描述

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 moduleenter event loop // (described earlier)if (event loop terminated normally) // i.e. no errorsdo callFinish() on system moduleclean up

callInitialize和callFinish的伪代码如下


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

01-模块的初始化

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

1.window–>
2.preferrence–>
3.general–>
4.keys–>
来添加重载快捷键
在这里插入图片描述

模块调试:
EV<<“initialize!!!”<<"("<<x<<","<<y<<")"<<endl;

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()
在这里插入图片描述

例子阅读

官方 19 个 tictoc

仿真主要参考的资料

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

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

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

01 睡眠实现


http://chatgpt.dhexx.cn/article/afowTXJT.shtml

相关文章

无图无真相!设计模式概览

设计模式太多&#xff0c;最近没有更新&#xff0c;最后想想还是看一点更新一点吧。

Mac系统Safari浏览器启动无图模式

有的时候我们用热点上网&#xff0c;图片的出现会消耗大量的流量&#xff0c;这时候就需要启动无图模式不加载图片。 步骤&#xff1a;启动Safari浏览器->偏好设置->高级->勾选“在菜单栏中显示“开发”菜单”->点击开发菜单->勾选“停用图像” 转载于:https://…

无图无真相!工厂模式结构

抽象类工厂模式结构图&#xff1a; 接口类工厂模式结构图&#xff1a; 工厂模式示例代码 工厂静态方法说明

设计模式之代理模式(Proxy Pattern)

1.概念 为其他对象提供一种代理&#xff0c;以控制对这个对象的访问。代理对象起到中介作用&#xff0c;可去掉功能或者增加额外功能。 2.角色 抽象主题角色&#xff08;Subject&#xff09;&#xff1a;声明了目标对象和代理对象的共同接口&#xff0c;这样一来在任何可以使用…

树莓派4B配置Selenium库+设置无图无头属性

写一个树莓派4B配置selenium库&#xff0c;并成功调用浏览器进行自动化爬虫 本文会手把手教你配置环境&#xff0c;并带你写第一个selenium爬虫程序 使用版本说明 系统&#xff1a;官网2020-02-13-raspbian-buster-full Python&#xff1a;树莓派自带的3.7.3 以下所有的pip操…

屏蔽图片的chrome插件

有时候觉得CSDN博客的广告好烦啊&#xff0c;还有有些看小说的网站&#xff0c;于是找了个屏蔽图片的插件。 效果如图&#xff1a; 之前博客的广告 之后&#xff1a; CSDN的广告有字&#xff0c;所以不会完全不显示&#xff0c;但是有很多小说网站都可以直接全部屏蔽掉…

python selenium playwright库使用教程 破解网页防止开发者模式 截取数据请求

安装chromedriver 下载 chromedriver的版本一定要与Chrome的版本一致&#xff0c;不然就不起作用。 有两个下载地址&#xff1a; 1、http://chromedriver.storage.googleapis.com/index.html 2、CNPM Binaries Mirror 当然&#xff0c;你首先需要查看你的Chrome版本&…

360浏览器,怎么开启无图片模式,在开热点的时候,省流量

如果某些网站&#xff0c;我需要加载图片&#xff0c;如csdn上传图片的时候。 这时候我们需要进行放权&#xff1a;

【Playwright】关于无痕模式与无头模式

Playwright的无头模式和无痕模式 无头模式 无头模式指的是自动测试框架在执行过程中不打开浏览器窗口的功能。在Playwright中&#xff0c;关闭无头模式会在测试代码执行过程中显示浏览器窗口&#xff0c;执行的过程会显示在浏览器的上。 # 以下代码以Playwright的同步API为例…

爬虫之selenium开启无界面模式

绝大多数服务器是没有界面的&#xff0c;selenium控制谷歌浏览器也是存在无界面模式的&#xff08;又称之为无头模式&#xff09; 开启无界面模式的方法 实例化配置对象 options webdriver.ChromeOptions()配置对象添加开启无界面模式的命令 options.add_argument("--he…

locust入门 -6 无图模式和分布式执行

无图模式 无图模式即不通过UI界面进行执行locust测试用例。locust提供了命令参数&#xff0c;我们只需要在执行时添加一个--headless标签即可 “Disable the web interface, and start the test immediately. Use -u and -t to control user count and run time ” 以下内容为…

Python爬虫配置Selenium库+设置无图无头属性

出一个最新windows下配置selenium全环境的教程~ 本文会手把手教你配置环境&#xff0c;并带你写第一个selenium爬虫程序 环境配置 1.安装Selenium库 Python和Anaconda-Python中并不包含Selenium包&#xff0c;这里我们要安装一下Selenium这个包 以下三种方式认选一种即可&am…

chrome如何进入无图模式?

chrom只显示文字不显示图片 隐私和安全-图片 可以设置所有网站都不显示图片 自定义指定网站不允许显示图片

locust入门 —— 无图模式和分布式执行

无图模式 无图模式即不通过UI界面进行执行locust测试用例。locust提供了命令参数&#xff0c;我们只需要在执行时添加一个--headless标签即可 “ Disable the web interface, and start the test immediately. Use -u and -t to control user count and run time ” 以下内容为…

PC端浏览器如何设置无图模式

以谷歌浏览器为例&#xff0c;注意有些浏览器并不支持该功能。 1&#xff09;打开自定义与控制 2&#xff09;选择设置 3&#xff09;查看左边状态栏&#xff0c;选择高级设置--》隐私设置和安全性 4&#xff09;选择内容设置 5&#xff09;图片 6&#xff09;选择不显示任何图…

火狐浏览器设置无图模式

步骤一 打开火狐浏览器&#xff0c;在地址栏输入about:config&#xff0c;然后回车 步骤二 在出来的页面中搜索&#xff1a;permissions.default.image 步骤三 把 permissions.default.image 设成 2 保存。 效果

万向锁的简单数学解释

我们知道用欧拉角表示空间的旋转&#xff0c;容易产生万向锁(Gimbal Lock)问题&#xff0c;这常常不太容易理解。下面给出一个直观的数学解释。 欧拉角表示的空间旋转&#xff0c;可以用绕三个坐标轴的旋转矩阵的乘积表示 万向锁问题就是出现在这种表示方法中。 假如我们令 β…

万向锁的理解

万向锁 万向锁这个概念其实还是不大好理解的&#xff0c;看了很多的博客&#xff0c;虽然看起来他们讲的很有道理&#xff0c;可还是想不通。 希望我这篇文章能讲清楚。。。 万向锁产生的根本原因是绕三个轴的旋转不是同时进行的&#xff0c;想象一下我们旋转矩阵的推导是不是…

万向锁问题详解,以Unity为例

转载自&#xff1a;https://blog.csdn.net/fengya1/article/details/50721768 根据上面的说明两个旋转面&#xff08;圆圈&#xff09;怎么会共面&#xff0c;让我迷糊。假设共面&#xff0c;那这两个旋转面的法线应该是旋转轴&#xff0c;要想两个面共面&#xff0c;那旋转轴肯…

UE4解决万向锁问题

万向锁 目录万向锁的来源Unity中最简单的万向锁UE4最简单万向锁解决方案四元数与欧拉角之间的转换参考链接 目录 万向锁的来源 简单而言&#xff0c;万向锁就是由于物体在进行旋转时&#xff08;前提是通过欧拉角进行旋转&#xff09;&#xff0c;当旋转到某个特定角度会导致…