NS3學習記錄(四)--加入新模型及聚合Aggregate

1.官方描述(聚合的描述)

在ns-2中已經被廣泛使用的繼承和多態,它們被用來擴展協議模型,正是這種強力的認知才促成了NS-3的對象聚合系統。例如,特例化的TCP版本,如RenoTcpAgent就是通過重寫方法繼承自TcpAgent的。

然而,在ns-2中存在兩個問題,即downcasts和“weak base class”。

    1.Downcasting指的是,通過使用基類對象的指針,在運行時查詢該指針來找到其類型信息,通常用來將基類的指針詳細化地強制轉換爲子類的指針,用來去使用子類API的這樣一個過程。

    2. Weak baseclass指的是,一個類不能夠有效地被重用或被繼承,因爲它缺少了一些必要的功能,導致開發者必須重新編輯修改這些基類,從而導致基類API調用的增生,而且其中一些可能會使得其全部子類出現不正確的語義。

 

ns-3 使用查詢接口設計模式來避免這些問題。該設計基於 Component ObjectModel 和 GNOME Bonobo的基礎。儘管現在替代構件的完全的二進制兼容性還不被支持,但我們努力簡化語法和對模型編寫者的影響。

====================

 

 

聚合的例子 Aggregation example

ns-3 中,class Node 是使用聚合的一個很好的例子。注意ns-3 中沒有類Node的派生類(比如類InternetNode等),而是將構件(各種協議)聚合到節點中。

我們來研究一下Ipv4 協議是如何被加入節點的。

   

static void

    AddIpv4Stack(Ptr node)

    {

         Ptr ipv4 =CreateObject ();

        ipv4->SetNode (node);

        node->AggregateObject(ipv4);

         Ptr ipv4Impl= CreateObject ();

        ipv4Impl->SetIpv4(ipv4);

        node->AggregateObject(ipv4Impl);

    }

注意Ipv4 協議是用 CreateObject() 創建的。接着Ipv4 協議被聚合到節點中。

這樣,基類Node 就不需要被編輯來使得用戶使用指向基類Node 的指針來訪問Ipv4接口;用戶可以在程序運行時來向節點請求指向該節點的Ipv4 接口的指針。

注意:將多於一個的同一類型的對象聚合到某個ns3::object是編程錯誤。所以,如果想要存儲一個節點的所有活動的sockets,聚合是不可選的。


2.自我經驗:


很多時候我們新加入了一個模型,希望這個新模型和現有的節點模型或者設備模型可以建立一對一的聯繫,這個時候就用到了ns3中的聚合技術。但由於ns3具有自己的代碼風格和代碼標準,研究了很久才成功。下面先介紹一下如何加入新的模型,此處設新模型爲uan-table,然後將新模型與節點node進行聚合的過程。


1)加入新模型

先貼出兩個代碼uan-table.h和uan-table.cc。

 uan-table.h

#ifndef UAN_TABLE_H               //#ifnedef,#define和#endif都是ns3代碼規範中需要寫的東西

#define UAN_TABLE_H            
#include "ns3/object.h"               //加入ns3/object.h的引用,若不特殊加載,則類繼承時則是c++中默認的object類
namespace ns3                           //命名空間爲ns3,也可以再設置一級層次
{
    class UanRoutingTable: public Object{     //繼承object類,纔可以繼承ptr指針,纔可以用於聚合。
        public:
            static TypeId GetTypeId(void);       //所有的類都要有此函數來確定其類型,通過類型可以進行註冊,創建
            UanRoutingTable();                       //構造函數
            virtual ~UanRoutingTable();             //析構函數採用虛函數的方式來實現多態效果
            uint16_t idd;
            void SetString(uint16_t i);               //簡單的兩個函數,用於檢測聚合效果
            uint16_t getString();
    };
}
#endif


uan-table.cc

#include "uan-table.h"                         //引入相應頭文件
#include "ns3/log.h"                            //引入日誌頭文件
NS_LOG_COMPONENT_DEFINE("UanRoutingTable");        
namespace ns3{
    NS_OBJECT_ENSURE_REGISTERED(UanRoutingTable);   //此處注意,一定要寫這個方法,這個方法將
                                                    //這個類登記進入內核中,在ptr聲明此類的時候才能可用
    TypeId UanRoutingTable::GetTypeId(void)  {                       
        static TypeId tid = TypeId("ns3::UanRoutingTable").SetParent ();
        return tid;                                 //定義此類的標誌字符串
    }
    UanRoutingTable::UanRoutingTable()  {    }
    UanRoutingTable::~UanRoutingTable()   {    }
    void UanRoutingTable::SetString(uint16_t idd) {  
        this->idd = idd;
    }
    uint16_t UanRoutingTable::getString(){        //此方法可獲得88這個數。
        this->idd = 88;
        return this->idd;
    }
}


新添加兩個類需要注意這樣一些問題:


  1. 由於新增加了兩個文件,必須挑選相應的文件夾將其放入,我選擇了scr/uan/model下面。挑選完之後,需要在wscript中進行登記,將.h和.cc文件寫入相應位置中。
  2. 察看ns-3 coding style 要了解其代碼風格。
  3. 要繼承object類作爲基類。因爲可以從Object中繼承一些特殊屬性:ns-3的類型和屬性系統;對象聚合系統;智能指針參考記數系統(Ptr)。

下面是在腳本中如何使用聲明新類和聚合。

Ptr table=CreateObject();//注意,此處必須用CreateObject纔可成功聚合,否則類型不匹配
            m_sinks.Get(0)->AggregateObject(table);   //將其與節點聚合
            std::cout << m << "test:" <<m_sinks.Get(0)->GetObject()->getString()<< std::endl;    //測試是否可以正確取到聚合後對象的函數



這是就可看到正確輸出了0test:88

聚合成功。


發佈了9 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章