Tictoc3例子

news2024/11/22 12:00:16

在tictoc3中,实现了让 tic 和 toc 这两个简单模块之间传递消息,传递十次后结束仿真。
首先来介绍一下程序中用到的两个函数:
1.omnetpp中获取模块名称的函数

 virtual const char *getName() const override  {
     return name ? name : "";
 }

2.定义及初始化消息的函数

cMessage *msg = new cMessage("tictocMsg");

接着来看一下网络描述文件 tictoc3.ned, 这个文件中定义了所仿真的网络是什么样子的。

//
// This file is part of an OMNeT++/OMNEST simulation example.
//
// Copyright (C) 2003-2015 Andras Varga
//
// This file is distributed WITHOUT ANY WARRANTY. See the file
// `license' for details on this and other legal matters.
//
simple Txc3
{
    parameters:
        @display("i=block/routing");
    gates:
        input in;
        output out;
}

//
// Same as Tictoc2.
//
network Tictoc3
{
    submodules:
        tic: Txc3 {
            parameters:
                @display("i=,cyan");
        }
        toc: Txc3 {
            parameters:
                @display("i=,gold");
        }
    connections:
        tic.out --> {  delay = 100ms; } --> toc.in;
        tic.in <-- {  delay = 100ms; } <-- toc.out;
}

可以看到,在上述的代码段中,定义了一个简单模块的结构Txc3,里面包含了一个输入门in 和输出门 out 。随后在 Tictoc3 这个网络中,创建了Txc3 的两个实例 tic 和 toc ,并创建了它们之间的连接,即两条时延为100ms 的信道,使两模块可以互相通信。
定义好了ned文件后需要把Tictoc3这个网络配置到初始化文件omnetpp.ini当中,指明仿真所使用的是哪个网络。

[Config Tictoc3]
network = Tictoc3

最后我们来看一下tic 和 toc 之间的消息传递是怎么实现的,这就要前往表示行为的.cpp文件了。

//
// This file is part of an OMNeT++/OMNEST simulation example.
//
// Copyright (C) 2003-2015 Andras Varga
//
// This file is distributed WITHOUT ANY WARRANTY. See the file
// `license' for details on this and other legal matters.
//

#include <stdio.h>
#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;

/**
 * In this class we add a counter, and delete the message after ten exchanges.
 */
class Txc3 : public cSimpleModule
{
  private:
    int counter;  // Note the counter here

  protected:
    virtual void initialize() override;      
    virtual void handleMessage(cMessage *msg) override;  
};

Define_Module(Txc3);   //识别Txc3这个类

void Txc3::initialize()
{
    // Initialize counter to ten. We'll decrement it every time and delete
    // the message when it reaches zero.
    counter = 10;

    // The WATCH() statement below will let you examine the variable under
    // Tkenv. After doing a few steps in the simulation, double-click either
    // `tic' or `toc', select the Contents tab in the dialog that pops up,
    // and you'll find "counter" in the list.
    WATCH(counter);      //表示在仿真中可以查看当前这个变量的状态

    if (strcmp("tic", getName()) == 0) {
        EV << "Sending initial message\n";            //仿真界面输出信息
        cMessage *msg = new cMessage("tictocMsg");
        send(msg, "out");          //
    }
}

void Txc3::handleMessage(cMessage *msg)
{
    // Increment counter and check value.
    counter--;
    if (counter == 0) {
        // If counter is zero, delete message. If you run the model, you'll
        // find that the simulation will stop at this point with the message
        // "no more events".
        EV << getName() << "'s counter reached zero, deleting message\n";
        delete msg;
    }
    else {
        EV << getName() << "'s counter is " << counter << ", sending back message\n";
        send(msg, "out");
    }
}

我们来分析一下这个程序。首先在Txc3这个类中,定义了一个成员变量counter,这个是用来标记模块发送了多少的消息的;接着声明了两个方法:initialize() 和 handleMessage() , 其中 initialize()指明初始化的时候要做出什么样的操作,handleMessage(cMessage *msg)指明接收到消息的时候要做出什么样的处理。接下来分别解读一下这两个函数。
initialize()

void Txc3::initialize()
{
    // Initialize counter to ten. We'll decrement it every time and delete
    // the message when it reaches zero.
    counter = 10;

    // The WATCH() statement below will let you examine the variable under
    // Tkenv. After doing a few steps in the simulation, double-click either
    // `tic' or `toc', select the Contents tab in the dialog that pops up,
    // and you'll find "counter" in the list.
    WATCH(counter);      //表示

    if (strcmp("tic", getName()) == 0) {
        EV << "Sending initial message\n";          
        cMessage *msg = new cMessage("tictocMsg");
        send(msg, "out");         
    }
}

在这个函数中,首先初始化了Txc3类中的成员变量值为10; WATCH(counter)这条语句的作用是为了能够在仿真中可以查看当前这个变量的状态;接下来是判断当前模块是否为 tic,如果是的话就在仿真界面输出信息"Sending initial message",并创建一个新消息msg从tic模块的 out 门发送出去。这样就实现了让 tic 模块先传递消息给toc。然后我们来看一下初始化之后的样子,如下图所示:
image.png
从仿真日志里可以看出,在还没有开始tictoc3的仿真时,就完成了初始化网络的操作,即构建好tictoc3这个网络,并初始化 tic 和 toc 两模块之间的信道;而且初始化的时候会调用 initialize() 初始化两个模块tic 和 toc,对于toc模块的初始化就是创建出了这个模块,而对于 tic 模块则是在创建后向 toc 模块发送了一个cMessage消息,但是这个时候 toc 还没有收到,因为handleMessage(cMessage *msg)函数是在开始仿真的时候才会执行的。从下图中就可以看出,此时这个代表消息的红点还没有到达 toc 模块。
image.png
*handleMessage(cMessage msg)

void Txc3::handleMessage(cMessage *msg)
{
    // Increment counter and check value.
    counter--;
    if (counter == 0) {
        // If counter is zero, delete message. If you run the model, you'll
        // find that the simulation will stop at this point with the message
        // "no more events".
        EV << getName() << "'s counter reached zero, deleting message\n";
        delete msg;
    }
    else {
        EV << getName() << "'s counter is " << counter << ", sending back message\n";
        send(msg, "out");
    }
}

可以看到在这个函数中就没有区分是 tic 模块还是toc 模块了,那也就是说tic 和 toc 在收到对方发来的消息时所作的处理是一样的。首先会把自己的计时器counter减一,表示已经收到了一次消息了,接着判断counter的值有没有减到零,是的话就表示已经收到十次来自对方的消息了,这个时候就删除掉该消息,然后不再发送;如果没有减为零,先在仿真界面输出一下此时的counter值,接着把收到的消息 tictocMsg 从自己的 out 门发送出去。
接下来点击运行仿真,跟踪整体的仿真事件:
image.png
可以看到,在没有了事件时,仿真就会结束。
下面详细看一下仿真日志的输出:
image.png
当toc模块第十次收到tictocMsg这个消息时,它的counter值就递减到零了,所以Event19 就是最后一个事件。由于是 tic 先发送消息给 toc 的,所以在传递的过程中,一定是 toc 模块先收到最后一个消息。
此外,前面提到WATCH(counter)语句是保证在仿真中可以查看counter的状态,所以在仿真中只需双击 tic 或 toc 模块就可以看到对应模块的 counter 值了。如下图所示:
image.png
可见,此时toc模块的 counter 值为8,也就是说toc已经收到了两次来自tic的消息了。
以上就是对 tictoc 的第三个例子的解读,若有更加通透的见解欢迎评论区留言分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1511129.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Rust 安装与版本更新

Rust 简介 Rust &#xff0c;一门赋予每个人构建可靠且高效软件能力的语言&#xff0c;主打内存安全。 2024年2月&#xff0c;在一份 19 页的报告《回归基础构件&#xff1a;通往安全软件之路》中&#xff0c;白宫国家网络主任办公室&#xff08;ONCD&#xff09;呼吁开发者使…

linux ,Windows部署

Linux部署 准备好虚拟机 连接好查看版本&#xff1a;java -version安装jdk 解压命令&#xff1a;tar -zxvf 加jdk的压缩文件名cd /etc 在编辑vim profile文件 在最底下写入&#xff1a; export JAVA_HOME/root/soft/jdk1.8.0_151&#xff08;跟自己的jdk保持一致&#xff0…

【网站项目】012医院住院管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Matlab中安装mltbx工具箱文件

准备 前提就是要已经下载好了相应的mltbx格式的工具箱文件 一般来说可以直接在开源的Github上下到相应的文件&#xff0c;这里以VeriStand Model Generation Support MATLAB add-on为例 注&#xff1a; 一般来说你可以下载到的文件有两种&#xff1a; Source Code &#xff…

实体店新模式探索:实体店如何转型与引流新策略

随着互联网的迅猛发展&#xff0c;线上购物逐渐成为了人们消费的主流方式。然而&#xff0c;实体店作为传统零售业的代表&#xff0c;依然具有其独特的价值和优势。 为了在这个变革的时代中保持竞争力&#xff0c;实体店必须积极探索新的模式&#xff0c;实现转型与引流。 作…

归并排序 刷题笔记

归并排序的写法 归并排序 分治双指针 1.定义一个mid if(l>r)return ; 2.分治 sort(q,l,mid); sort(q,mid1,r); 3. 双指针 int il,jmid,k0; 将双序列扫入 缓存数组 条件 while(i<mid&&j<r) 两个数列比较大小 小的一方 进入缓存数组 4. 扫尾 while(…

OpenHarmony教程指南—ArkTS时钟

简单时钟 介绍 本示例通过使用ohos.display 接口以及Canvas组件来实现一个简单的时钟应用。 效果预览 使用说明 1.界面通过setInterval实现周期性实时刷新时间&#xff0c;使用Canvas绘制时钟&#xff0c;指针旋转角度通过计算得出。 例如&#xff1a;"2 * Math.PI /…

MyBatis 实现复杂查询

#{ } 与 ${ } 的区别(重点) #{ } 与 ${ } 在MyBatis中都是用于替换SQL参数的, 主要以下几点不同: 方式不同: ${ } 是直接替换为传递的参数, #{ } 则是先预处理,然后再设置参数 安全性不同: ${ } 存在SQL注入的风险, #{ }则不存在安全问题使用场景不同: …

【GO】HTTP标准库1 - http协议基础知识

目录 一 http协议 1 http协议 2 http request 3 请求方法 4 URL 5 协议版本 6 请求头 7 Content-type 9 POST与GET区别 10 HTTP Response 11 常见的状态与话术 12 HTTP 响应头 13 完整的HTTP响应 14 HTTPS 一 http协议 1 http协议 HTTP&#xff08;HyperText Tra…

Python从0到100(四):Python中的运算符介绍

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

Centos7 安装postgresql14后无法连接数据库

1、数据库服务器允许外部访问5432端口。 2、postgresql.conf 3、pg_hba.conf a、制定某个IP&#xff08;192.168.0.107&#xff09;访问 b、指定ip段访问 允许10.1.1.0~10.1.1.255网段登录数据库 host all all 10.1.1.0/24 trust c、指定全网访问 host a…

盲盒抽卡机小程序——开启神秘之旅!

亲爱的朋友们&#xff0c;欢迎来到盲盒抽卡机小程序&#xff01;这里&#xff0c;是一个充满神秘与惊喜的世界&#xff0c;让你随时随地体验抽卡的乐趣。在这里&#xff0c;你可以轻松尝试各种盲盒&#xff0c;发现隐藏的宝藏&#xff0c;感受心跳加速的刺激。 【丰富多样的盲…

语音情感识别python项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 什么是语音情感识别&#xff1f; 语音情感识别&#xff0c;缩写为 SER&#xff0c;是试图从语音中识别人类情感和情感状态的行为。这是利用了这…

docker + nginx打包前端镜像

项目场景&#xff1a; 前端使用angular开发&#xff0c;Dockerfile如下&#xff1a; FROM nginx:1.16.1 AS base WORKDIR /app COPY nginx.conf.template /etc/nginx/ CMD ["/bin/bash", "-c", "envsubst ${APP_VERSION} < /app/index.html > …

Python环境安装及Selenium引入

Python环境安装 环境下载 Download Python | Python.org 环境安装 需使用管理员身份运行 查看环境是否安装成功 python --version 如果未成功则检查环境变量配置 安装 Selenium 库 pip install selenium Selenium 可以模拟用户在浏览器中的操作&#xff0c;如点击按钮、填写…

Vue3全家桶 - VueRouter - 【2】重定向路由

重定向路由 在路由规则数组中&#xff0c;可采用 redirect 来重定向到另一个地址&#xff1a; 通常是将 / 重定向到 某个页面&#xff1b; 示例展示&#xff1a; router/index.js&#xff1a;import { createRouter, createWebHashHistory, createWebHistory } from vue-route…

51单片机基础篇系列-中断系统处理过程中断编程

&#x1f308;个人主页:会编辑的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 80C51单片机中断处理过程 中断相应过程&#xff1a; 中断源有中断请求 此中断源的中断允许位为1 CPU开中断&#xff08;即EA-1&#xff09;.以上三条同时满足&#xff0c;CPU才有…

okcc呼叫中心外呼任务为何启动后会自动暂停?

OKCC呼叫中心系统是一套完整的呼叫中心与管理平台,为电话营销型企业专门设计的电销平台与客服平台。OKCC系统集电话营销功能与热线客服功能于一体,兼具呼入呼出功能。本呼叫中心支持独立的计费系统、话务系统、客户系统、工单管理系统,是一套完善的高效的呼叫中心系统 那我们在…

基于EasyCVR视频技术的流媒体视频融合与汇聚管理系统建设方案

流媒体视频融合与汇聚管理系统可以实现对各类模块化服务进行统一管理和配置等操作&#xff0c;可实现对应用服务的整合、管理及共享&#xff0c;以标准接口的方式&#xff0c;业务平台及其他第三方业务平台可以方便地调用各类数据&#xff0c;具有开放性和可扩展性。在流媒体视…

如何不依赖Unity直接解压unitypackage的内容

使用场景 我们都知道unity的资源导出是导出成.unitypackage文件,如果要里面的内容,得打开Unity,将unitypackage导入进去才能看到里面的内容。 但是很多时候我们下了几十个unitypackage资源包,又不清楚好不好用,而且导入之后编译特别慢,unity又不提供批量解压的功能,所…