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:" <GetObject()->getString()<< std::endl;    //测试是否可以正确取到聚合后对象的函数



这是就可看到正确输出了0test:88

聚合成功。


你可能感兴趣的:(ns3)