OMNet++学习笔记(三): tictoc例程学习笔记--Turning it Into a Real Network

本博客继续记录我学习tictoc教程中的一些学习笔记,以便后续复习。

Part 4 - Turning it Into a Real Network

1. 多于两个节点

实现更真实的网络:从两个节点拓展到多个节点,其中节点0生成消息,其他节点则持续以随机方向传递该消息,直到它抵达预定的目标节点3。

① NED

simple Txc10
{
    parameters:
        @display("i=block/routing");
    gates:
        input in[];  // []代表定义的是 gate vector
        output out[];
}

network Tictoc10
{
    submodules:
        tic[6]: Txc10;
    connections:
        tic[0].out++ --> {  delay = 100ms; } --> tic[1].in++;
        tic[0].in++ <-- {  delay = 100ms; } <-- tic[1].out++;

        tic[1].out++ --> {  delay = 100ms; } --> tic[2].in++;
        tic[1].in++ <-- {  delay = 100ms; } <-- tic[2].out++;

        tic[1].out++ --> {  delay = 100ms; } --> tic[4].in++;
        tic[1].in++ <-- {  delay = 100ms; } <-- tic[4].out++;

        tic[3].out++ --> {  delay = 100ms; } --> tic[4].in++;
        tic[3].in++ <-- {  delay = 100ms; } <-- tic[4].out++;

        tic[4].out++ --> {  delay = 100ms; } --> tic[5].in++;
        tic[4].in++ <-- {  delay = 100ms; } <-- tic[5].out++;
}

② .cc

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

using namespace omnetpp;


class Txc10 : public cSimpleModule
{
  protected:
    virtual void forwardMessage(cMessage *msg);
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Txc10);

void Txc10::initialize()
{
    if (getIndex() == 0) {
        // 只有tic[0]才发出消息,这里是利用自己给自己发self-message来实现的
        char msgname[20];
        sprintf(msgname, "tic-%d", getIndex());
        cMessage *msg = new cMessage(msgname);
        scheduleAt(0.0, msg);
    }
}

void Txc10::handleMessage(cMessage *msg)
{
    if (getIndex() == 3) {
        // 目标的终点
        EV << "Message " << msg << " arrived.\n";
        delete msg;
    }
    else {
        // 这里转发消息
        forwardMessage(msg);
    }
}

void Txc10::forwardMessage(cMessage *msg)
{
    // 随机选择一个output gate发送消息
    int n = gateSize("out");
    int k = intuniform(0, n-1);

    EV << "Forwarding message " << msg << " on port out[" << k << "]\n";
    send(msg, "out", k);
}

③ .ini文件

[General]
[Tictoc10]
network = Tictoc10

2. 信道和内部类型定义

在上面的网络定义中,network definition变得十分复杂且长,特别是定义不同module的connect的部分。因此本小节的目的是简化它们。

我们注意到,所有connections具有相同的delay参数,因为我们可以为connects专门创建一个type,叫做channels,来简化modules。j具体代码如下:

①NED

simple Txc11
{
    parameters:
        @display("i=block/routing");
    gates:
        input in[];  // declare in[] and out[] to be vector gates
        output out[];
}


network Tictoc11
{
    types:
        // 在network内部增加一个types section,它们只在这个network内可见
        // 被称为 local or inner type
        channel Channel extends ned.DelayChannel {
            delay = 100ms;
        }
    submodules:
        tic[6]: Txc11;
    connections:
        tic[0].out++ --> Channel --> tic[1].in++;
        tic[0].in++ <-- Channel <-- tic[1].out++;

        tic[1].out++ --> Channel --> tic[2].in++;
        tic[1].in++ <-- Channel <-- tic[2].out++;

        tic[1].out++ --> Channel --> tic[4].in++;
        tic[1].in++ <-- Channel <-- tic[4].out++;

        tic[3].out++ --> Channel --> tic[4].in++;
        tic[3].in++ <-- Channel <-- tic[4].out++;

        tic[4].out++ --> Channel --> tic[5].in++;
        tic[4].in++ <-- Channel <-- tic[5].out++;
}

② .cc ③.ini 没有改变

3. 增加inout gate替代原来的input和output gates

因为连接都是双向的,所以可以直接用two-way (or so called inout) gates来替代原来分离的input和output gates

① NED

simple Txc12
{
    parameters:
        @display("i=block/routing");
    gates:
        inout gate[];  // 定义 two way connections 
}

network Tictoc12
{
    types:
        channel Channel extends ned.DelayChannel {
            delay = 100ms;
        }
    submodules:
        tic[6]: Txc12;
    connections:
        // 因为是双向门,所以可以直接用<-->
        tic[0].gate++ <--> Channel <--> tic[1].gate++;
        tic[1].gate++ <--> Channel <--> tic[2].gate++;
        tic[1].gate++ <--> Channel <--> tic[4].gate++;
        tic[3].gate++ <--> Channel <--> tic[4].gate++;
        tic[4].gate++ <--> Channel <--> tic[5].gate++;
}

② .cc

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

using namespace omnetpp;


class Txc12 : public cSimpleModule
{
  protected:
    virtual void forwardMessage(cMessage *msg);
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Txc12);

void Txc12::initialize()
{
    if (getIndex() == 0) {
        char msgname[20];
        sprintf(msgname, "tic-%d", getIndex());
        cMessage *msg = new cMessage(msgname);
        scheduleAt(0.0, msg);
    }
}

void Txc12::handleMessage(cMessage *msg)
{
    if (getIndex() == 3) {
        EV << "Message " << msg << " arrived.\n";
        delete msg;
    }
    else {
        forwardMessage(msg);
    }
}

void Txc12::forwardMessage(cMessage *msg)
{
    // 从“out”变成"gate"
    int n = gateSize("gate");
    int k = intuniform(0, n-1);

    EV << "Forwarding message " << msg << " on gate[" << k << "]\n";
    send(msg, "gate$o", k);
}

4. 定义 message 类

如果一个网络中存在多个消息,而每个消息都用硬编码 tic[3], 这将导致在编写message的handleMessage函数时很麻烦,因此我们定义message类,且这个类只需要定义在.msg文件中,然后makefile中会利用message compiler, opp_msgc, 来生成tictoc13_m.h和tictoc13_m.cc。它们将包含一个[cMessage]的子类,该类为message类的每个字段提供getter和setter方法,具体如下:

① tictoc13.msg

message TicTocMsg13
{
    int source;
    int destination;
    int hopCount = 0;
}

② tictoc13.ned: 相较于前面,没有改动

simple Txc13
{
    parameters:
        @display("i=block/routing");
    gates:
        inout gate[];
}

network Tictoc13
{
    types:
        channel Channel extends ned.DelayChannel {
            delay = 100ms;
        }
    submodules:
        tic[6]: Txc13;
    connections:
        tic[0].gate++ <--> Channel <--> tic[1].gate++;
        tic[1].gate++ <--> Channel <--> tic[2].gate++;
        tic[1].gate++ <--> Channel <--> tic[4].gate++;
        tic[3].gate++ <--> Channel <--> tic[4].gate++;
        tic[4].gate++ <--> Channel <--> tic[5].gate++;
}

③ .cc

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

using namespace omnetpp;

// 这个头文件是message compiler利用tictoc13.msg生成的,其中有cMessage的子类
#include "tictoc13_m.h"


class Txc13 : public cSimpleModule
{
  protected:
    virtual TicTocMsg13 *generateMessage();
    virtual void forwardMessage(TicTocMsg13 *msg);
    virtual void initialize() override;
    virtual void handleMessage(cMessage *msg) override;
};

Define_Module(Txc13);

void Txc13::initialize()
{
    // Module 0发送第一个消息
    if (getIndex() == 0) {
        // 将第一个消息作为self-message,方便后续消息的处理
        TicTocMsg13 *msg = generateMessage();
        scheduleAt(0.0, msg);
    }
}

void Txc13::handleMessage(cMessage *msg)
{
    // C++ 强制指针类型转换
    TicTocMsg13 *ttmsg = check_and_cast<TicTocMsg13 *>(msg);

    if (ttmsg->getDestination() == getIndex()) {
        EV << "Message " << ttmsg << " arrived after " << ttmsg->getHopCount() << " hops.\n";
        bubble("ARRIVED, starting new one!");
        delete ttmsg;

        EV << "Generating another message: ";
        TicTocMsg13 *newmsg = generateMessage();
        EV << newmsg << endl;
        forwardMessage(newmsg);
    }
    else {
        forwardMessage(ttmsg);
    }
}

TicTocMsg13 *Txc13::generateMessage()
{
    // 随机生成dest
    int src = getIndex();  // our module index
    int n = getVectorSize();  // module vector size
    int dest = intuniform(0, n-2);
    if (dest >= src)
        dest++;

    char msgname[20];
    sprintf(msgname, "tic-%d-to-%d", src, dest);

    // 创建message并且设置src和dest
    TicTocMsg13 *msg = new TicTocMsg13(msgname);
    msg->setSource(src);
    msg->setDestination(dest);
    return msg;
}

void Txc13::forwardMessage(TicTocMsg13 *msg)
{
    // 增加跳数
    msg->setHopCount(msg->getHopCount()+1);

    int n = gateSize("gate");
    int k = intuniform(0, n-1);

    EV << "Forwarding message " << msg << " on gate[" << k << "]\n";
    send(msg, "gate$o", k);
}

总结

在本节中,我们了解了如何定义信道、inout gate和message类,这为我们快速构建大规模网络提供了技术基础

 

 

 

 

 

  

posted @ 2025-11-05 14:11  碳酸钾K2CO3  阅读(8)  评论(0)    收藏  举报