前言
事实上ns3的官方手册很全,相关书籍也是有的,官网先贴在这里:
ns-3 | a discrete-event network simulator for internet systemsa discrete-event network simulator for internet systemshttps://www.nsnam.org/相关的脚本介绍也都有一些:
ns-3.35_wifi-he-network.cc_ns-3网络仿真工具wifi脚本解析_wifi脚本网络拓扑_ns-3wifi6吞吐脚本关键注释_吞吐部分_基础ns-3_ns3.35-CSDN博客
ns-3-model-library wifi 浅析_ns-3wifi部分解析_ns-3网络模拟器wifi部分文档分析_Part1_ns3 wifiphy物理层冲突-CSDN博客
ns-3-model-library wifi 浅析_ns-3wifi部分解析_ns-3网络模拟器wifi部分文档分析_Part2_yansphy-CSDN博客
不过现有的要么版本老旧,要么过于现象化,不够本质,正好我最近分析了下官方手册,在这里分享给大家——需要更加完整的内容,可以直接去官网。
Configuration and Attributes
在 ns-3 模拟中,配置有两个主要方面:
- 模拟拓扑和对象的连接方式。
- 在拓扑中实例化的模型使用的值。
本章重点介绍上述第二项:ns-3 用户如何组织、记录和修改 ns-3 中使用的许多值。ns-3 属性系统如何在模拟器中收集跟踪和统计信息的基础。在本章的课程中,我们将讨论设置或修改 ns-3 模型对象使用的值的各种方法。按特异性递增的顺序,这些是:
“特异性”是指表中后面几行中的方法会覆盖由早期方法设置的值,并且通常比早期方法影响更少的实例。在深入研究属性值系统的细节之前,回顾一下 Object 类的一些基本属性会有所帮助。
Object Overview
ns-3 从根本上说是一个基于 C++ 对象的系统。我们的意思是新的 C++ 类(类型)可以像往常一样声明、定义和子类化。许多 ns-3 对象继承自 Object 基类。这些对象具有一些额外的属性,我们利用这些属性来组织系统和改进对象的内存管理:
“元数据”系统,将类名链接到有关对象的大量元信息,包括:
- 子类的基类
- 子类
- 子类的 “attributes” 集
- 每个属性是可修改还是只读,
- 每个属性允许的值范围。
引用计数智能指针实现,用于内存管理。
使用属性系统的 ns-3 对象派生自 Object 或 ObjectBase。我们将讨论的大多数 ns-3 对象都派生自 Object,但少数位于智能指针内存管理框架之外的对象派生自 ObjectBase。让我们回顾一下这些对象的几个属性。
智能指针
如 ns-3 教程中所述,ns-3 对 象由引用计数智能指针实现类 Ptr 管理内存。智能指针在 ns-3 API 中广泛使用,以避免传递对可能导致内存泄漏的堆分配对象的引用。对于大多数基本用法 (语法),请将智能指针视为常规指针:
Ptr<WifiNetDevice> nd = ...;
nd->CallSomeFunction();
// etc.
那么,如何获得指向对象的智能指针,如本示例的第一行所示?
创建对象
正如我们在上 面的 内存管理和类 Ptr 中所讨论的,在最低级别的 API 中,Object 类型的对象不会像往常一样使用 operator
new 进行实例化,而是通过名为 CreateObject() 的模板化函数进行实例化。创建此类对象的典型方法如下:
Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice>();
您可以将其视为在功能上等效于:
WifiNetDevice* nd = new WifiNetDevice();
从 Object 派生的对象必须使用 CreateObject() 在堆上分配。可以从 ObjectBase 派生的那些,例如 ns-3 帮助程序函数以及数据包标头和尾部,可以在堆栈上分配。在某些脚本中,您可能不会在代码中看到很多 CreateObject() 调用;这是因为实际上有一些helper 程序对象正在为您执行 CreateObject() 调用。
TypeId
Ns3做的object基类里面带好了TypeID,所以后面Node之类的只要继承Object,就可有TypeID
从类 Object 派生的 ns-3 类可以包含一个名为 TypeId 的元数据类,该类记录有关该类的元信息,以便在 Object 聚合和组件管理器系统中使用(都在GetTypeId里面了 ):
- 标识类的唯一字符串。
- 元数据系统中子类的基类。
- 子类中的可访问构造函数集。
- 类的可公开访问的属性(“attributes”)的列表。
对象摘要
将所有这些概念放在一起,让我们看一个具体的例子:类 Node。公共头文件 node.h 有一个声明,其中包含静态 GetTypeId() 函数调用:
class Node : public Object
{
public:
static TypeId GetTypeId();
...
//这在 node.cc 文件中定义如下:
TypeId
Node::GetTypeId()
{
static TypeId tid = TypeId("ns3::Node")
.SetParent<Object>()
.SetGroupName("Network")
.AddConstructor<Node>()
.AddAttribute("DeviceList",
"The list of devices associated to this Node.",
ObjectVectorValue(),
MakeObjectVectorAccessor(&Node::m_devices),
MakeObjectVectorChecker<NetDevice>())
.AddAttribute("ApplicationList",
"The list of applications associated to this Node.",
ObjectVectorValue(),
MakeObjectVectorAccessor(&Node::m_applications),
MakeObjectVectorChecker<Application>())
.AddAttribute("Id",
"The id(unique integer) of this Node.",
TypeId::ATTR_GET, // allow only getting it.
UintegerValue(0),
MakeUintegerAccessor(&Node::m_id),
MakeUintegerChecker<uint32_t>())
;
return tid;
将 ns-3Object 类的 TypeId 视为运行时类型信息 (RTTI) 的扩展形式。C++ 语言包括一种简单的 RTTI,以支持 dynamic_cast 和 typeid 运算符。上述定义中的 SetParent<Object>() 调用与我们的对象聚合机制结合使用,以允许在 GetObject() 期间在继承树中安全地进行向上和向下转换。它还使子类能够继承其父类的 Attributes。AddConstructor<Node>() 调用与我们的抽象对象工厂机制结合使用,以允许我们构造 C++ 对象,而无需强制用户知道她正在构造的对象的具体类。对 AddAttribute() 的三次调用将给定字符串与类中的强类型值相关联。请注意,您必须提供帮助字符串,该字符串可能会显示,例如,通过命令行处理器显示。每个 Attribute 都与用于访问对象中的基础成员变量的机制相关联(例如,MakeUintegerAccessor() 告诉泛型 Attribute 代码如何访问上面的节点 ID)。还有一些 “Checker” 方法用于