Oment++ 初學者教程 第4節-將其轉變爲真實網絡

4.1兩個以上的節點

如今,咱們將邁出一大步:建立幾個tic模塊並將它們鏈接到網絡中。如今,咱們將使它們的工做變得簡單:一個節點生成一條消息,其餘節點繼續沿隨機方向扔消息,直到它到達預約的目標節點爲止。NED文件將須要進行一些更改。首先,該Txc模塊將須要具備多個輸入和輸出門:數組

simple Txc10
{
    parameters:
        @display("i=block/routing");
    gates:
        input in[];  //聲明input,ouput兩種類型的gate數組
        output out[];
}

數組[ ]多個門變成gate向量。向量的大小(門數)將在咱們使用Txc構建網絡的地方肯定。安全

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++;
}

在這裏,咱們建立了6個模塊做爲模塊向量,並將它們鏈接起來。
生成的拓撲以下所示:

在此版本中,tic[0]將生成要發送的消息。這是在函數initialize()的幫助下完成的,該getIndex()函數返回向量中模塊的索引。
代碼的forwardMessage()實質是handleMessage()每當消息到達節點時咱們從中調用的函數。它繪製一個隨機的gate number,並在該gate上發送message。網絡

void Txc10::forwardMessage(cMessage *msg)
{
    // 咱們選擇隨機的一個gate發送信息
    // 咱們在0~out[]數組長度之間選擇一個隨機數
    int n = gateSize("out");
    int k = intuniform(0, n-1);

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

當消息到達時tic[3]handleMessage()它將刪除該消息。
請參閱txc10.cc中的完整代碼
練習
您會注意到,這種簡單的「路由」效率不是很高:一般,數據包會在兩個節點之間不斷跳動一段時間,而後再發送到另外一個方向。若是節點不將數據包發送回發送方,則能夠在某種程度上進行改進。實現這一點。提示:cMessage::getArrivalGate()cGate::getIndex()。請注意,若是消息不是經過門到達的,而是self-messages,則getArrivalGate()返回NULL
來源:tictoc10.nedtxc10.ccomnetpp.inidom

4.2信道和內部類型定義

咱們新的網絡定義變得很是複雜冗餘,尤爲是鏈接部分。讓咱們嘗試簡化它。咱們注意到的第一件事是,鏈接始終使用相同的delay參數。與簡單模塊相似,能夠爲鏈接建立類型(它們稱爲信道)。咱們應該建立一個指定延遲參數的信道類型,並將該類型用於網絡中的全部鏈接。函數

network Tictoc11
{
    types:
        channel Channel extends ned.DelayChannel {
            delay = 100ms;
        }
    submodules:

如您所見,咱們經過添加一個types字段在網絡定義中定義了新的信道類型。此類型定義僅在網絡內部可見。它稱爲局部或內部類型。若是願意,您也能夠將簡單模塊用做內部類型。
筆記
咱們經過專門內置來建立通道DelayChannel。(能夠在ned包內找到內置信道。這就是爲何咱們在extends關鍵字後使用完整類型名稱的ned.DelayChannel的緣由
如今,讓咱們檢查一下該connections部分是如何更改的。this

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++;
}

如您所見,咱們僅在鏈接定義內指定通道名稱。這樣能夠輕鬆更改整個網絡的延遲參數。
來源:tictoc11.nedtxc11.ccomnetpp.ini編碼

4.3使用雙向鏈接

若是再檢查一下該connections部分,咱們將意識到每一個節點對都經過兩個鏈接鏈接。每一個方向一個。OMNeT ++ 4支持兩種方式的鏈接,所以讓咱們使用它們。
首先,咱們必須定義雙向(或所謂的inout)門,而不是以前使用的分離inputoutput門。url

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

connections部分以下所示:指針

connections:
        tic[0].gate++ <--> Channel <--> tic[1].gate++;//tic[0].gate[0]<-->tic[1].gate[0]
        tic[1].gate++ <--> Channel <--> tic[2].gate++;//tic[1].gate[1]<-->tic[2].gate[1]
        tic[1].gate++ <--> Channel <--> tic[4].gate++;
        tic[3].gate++ <--> Channel <--> tic[4].gate++;
        tic[4].gate++ <--> Channel <--> tic[5].gate++;
}

咱們已經修改了門名稱,所以咱們必須對C ++代碼進行一些修改。code

void Txc12::forwardMessage(cMessage *msg)
{
    // In this example, we just pick a random gate to send it on.
    // We draw a random number between 0 and the size of gate `gate[]'.
    int n = gateSize("gate");
    int k = intuniform(0, n-1);

    EV << "Forwarding message " << msg << " on gate[" << k << "]\n";
    // $o and $i 後綴被用來識別門的雙向輸入輸出
    send(msg, "gate$o", k);
}

筆記
gate名稱後的特殊$i$o後綴容許咱們分別使用鏈接的兩個方向。
來源:tictoc12.nedtxc12.ccomnetpp.ini

4.4定義咱們的message class

在此步驟中,再也不對目標地址進行硬編碼tic[3]-咱們繪製一個隨機目標,而後將目標地址添加到消息中。

最好的方法是重寫cMessage的子類並將目標添加爲數據成員。手動編碼消息類一般很乏味,由於它包含許多樣板代碼,所以咱們讓OMNeT ++爲咱們生成該類。消息類規範位於tictoc13.msg

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

筆記
有關消息的更多詳細信息,請參見OMNeT ++手冊的第6節
設置makefile以便調用消息編譯器opp_msgc並生成消息聲明tictoc13_m.htictoc13_m.cc從消息聲明生成(文件名是根據tictoc13.msg文件名而不是消息類型名生成的)。它們將包含一個TicTocMsg13從[ cMessage]子類生成的類;該類將爲每一個字段提供getter和setter方法。
咱們將tictoc13_m.h在咱們的C ++代碼中包含該代碼,而且能夠將其TicTocMsg13用做任何其餘類。

#include "tictoc13_m.h"

例如,咱們使用如下幾行generateMessage()來建立消息並填寫其字段。

TicTocMsg13 *msg = new TicTocMsg13(msgname);
    msg->setSource(src);
    msg->setDestination(dest);
    return msg;

而後,handleMessage()像這樣開始:

void Txc13::handleMessage(cMessage *msg)
{
    TicTocMsg13 *ttmsg = check_and_cast<TicTocMsg13 *>(msg);

    if (ttmsg->getDestination() == getIndex()) {

在handleMessage()的參數中,咱們將消息做爲cMessage*指針。可是,只有TicTocMsg13將msg轉換爲時,咱們才能訪問在中定義的字段TicTocMsg13*。純C樣式的強制轉換((TicTocMsg13 *)msg)是不安全的,由於若是消息_不是_a TicTocMsg13,則程序最終將崩潰,從而致使錯誤,而這是很難發現的。
C ++提供了一種稱爲的解決方案dynamic_cast。在這裏,咱們使用check_and_cast<>() OMNeT ++提供的功能:它嘗試經過強制轉換指針dynamic_cast,若是失敗,則會經過錯誤消息中止模擬,相似於如下內容:

在下一行中,咱們檢查目標地址是否與節點的地址相同。該getIndex()成員函數返回子模塊向量模塊的索引(記住,在咱們聲明是NED文件tic[6]: Txc13,因此節點地址0..5)。
爲了使模型的執行時間更長,在消息到達其目標以後,目標節點將生成另外一條具備隨機目標地址的消息,依此類推。閱讀完整的代碼:txc13.cc
運行模型時,它將以下所示:

您能夠單擊消息以在檢查器窗口中查看其內容。雙擊將在新窗口中打開檢查器。(您必須爲此暫時中止模擬,或者要很是快地處理鼠標)。檢查器窗口顯示許多有用的信息;消息字段可/以在「_目錄」_頁面上看到。

來源:tictoc13.nedtictoc13.msgtxc13.ccomnetpp.ini 練習 在此模型中,在任何給定時刻只有一條消息正在運行:節點僅在另外一條消息到達它們時才生成一條消息。咱們這樣作是爲了使跟蹤仿真變得更加容易。更改模塊類,以便改成按期生成消息。消息之間的間隔應該是一個模塊參數,返回指數分佈的隨機數。

相關文章
相關標籤/搜索