NS3入门:第一个程序first.cc

运行

环境配置

在VMware虚拟环境当中运行first.cc
首先安装虚拟机,然后配置环境:参考文章
NS3详细安装教程

安装完成之后,进入终端,运行以下代码
首先进入文件夹当中:

cd tarballs/ns-allinonr-3.34/ns-3.34

而后运行

sudo ./waf --run examples/tutorial/first

注意不是first.cc
随后出现以下效果first.cc运行效果

基本概念

在完成运行之后,我们了解一些运行first.cc需要知道的NS3仿真环境里的重要概念
NS3概念描述官方文档

节点Node

连接到网络的计算机设备成为主机,有时也称为终端系统。由于NS-3是网络模拟器,而不是特指互联网模拟器,所以我们不使用主机这个词,因为它紧密地与互联网及其协议联系在一起。相反,我们使用一个更通用的源自图论(图论〔Graph Theory〕是数学的一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。图论)的也被用于其他模拟器的术语——节点。
在 ns-3 中基本计算设备抽象被称作节点。这种抽象在 C++ 中用 Node 类表示。Node 类提供管理仿真中计算设备表现的方法
图论
你应该将一个 Node 当作一台你将要添加功能的计算机。可以添加**应用程序、协议栈和(有相关驱动的)外围卡(peripheral card)**使这台电脑能够做有用的工作。我们在 ns-3 的使用了相同的基本模型。

应用Application

通常,计算机软件分为两大类:系统软件和应用软件。
系统软件根据一些计算模型组织各类计算机资源,例如内存、处理器周期、磁盘、网络等。系统软件通常不使用这些资源来完成直接有益于用户的任务。应用获取和使用由系统软件控制的资源来完成用户的一些目标。

通常,系统软件和应用软件的分界线在于操作系统受限时特权级别的改变。在 ns-3 中没有真正的操作系统的概念尤其没有特权级别或者系统调用的概念。然而,我们有应用程序的概念。正如“真实世界”中,软件应用在计算机上运行执各种行任务,在模拟世界,ns-3 应用程序在 ns-3 节点上运行驱动模拟。

在 ns-3 中,对用户程序的基本抽象是应用。这种抽象在 C++ 中用 Application 类表示。Application 类提供管理在仿真中用户级应用的表现的方法。开发人员期望 Application 类能够在面向对象编程中定制以创建新的应用。 在本教程中,我们将使用定制的 Application 类被称为 UdpEchoClientApplication 和 UdpEchoServerApplication 类。 如你所料,这些应用程序组成一个客户端/服务器应用程序集,用于生成和回显模拟的网络数据包。

网络设备Net Device

曾经,如果你想将计算机连接到网络,你必须购买特定种类的网线和一种被称作外围卡(peripheral card)的硬件设备。如果外围卡能够实现一些网络功能,则它们被称为网络接口卡(Network Interface Card)或网卡(NIC)。今天,大多数计算机都带有内置的网络接口硬件,用户看不到这些构件。

如果没有软件驱动程序来控制硬件,网卡将无法工作。在 Unix(或 Linux),一块外设被归类为设备(device)。设备被设备驱动(device driver)所控制,网络设备(NIC)受网络设备驱动(network device driver)控制它们统称为 net device。 在 Unix 和 Linux 中,你通过诸如 eth0 之类的名字来查找这些设备

在 ns-3 中,net device 抽象涵盖了软件驱动和仿真硬件。一个 net device 被“安装”到一个节点中,以便在仿真中节点能和其他节点通过信道通信。就像在真实计算机中,节点可以经由多个 NetDevice 被连接到多个信道上。

Net device 的抽象在 C++ 中用 NetDevice 类表示。该 NetDevice 类提供用于管理 Node 和 Channel 对象连接的方法,并且可以由面向对象编程的开发者定制。在本教程中,我们将使用几个定制的 NetDevice 它们被称为 CsmaNetDevice、PointToPointNetDevice 和 WifiNetDevice。就像以太网网卡被设计成用于以太网网络,CsmaNetDevice 被设计成用于 CsmaChannel 、PointToPointNetDevice被设计成用于 PointToPointChannel、WifiNetNevice 被设计成用于 WifiChannel。

拓扑助手

为什么要有helper类?

在真实的网络中,你会发现添加了(或内置)网卡的主机。在 ns-3 中,我们要说的是,你会发现附加了 NetDevice 的 Node。在大型模拟网络中,你需要整理 Node、NetDevice、Channel 之间的各种连接。

因为 NetDevice 与 Node 之间的连接、NetDevice 与 Channel 之间的连接、分配 IP 地址等等都是 ns-3 中 常见的任务,所以我们提供了所谓的拓扑助手(Topology Helper)使这个尽可能容易。例如,创建 NetDevice、添加 MAC 地址、在节点上安装 Net Device、配置节点的协议栈,然后将 NetDevice 连接到一个信道需要很多 ns-3 核心操作来完成。将多个设备连接到多点信道上,然后将各个网络连接在一起成为互连网络,甚至需要更多的操作才能完成。为了方便使用,我们提供了 Topology Helper 对象,将这些不同的操作组成一个易于使用的模型。

第一个NS-3程序

first.cc在两个节点之间创建一个简单的点对点链接,并在节点之间回送(echo)单个数据包,让我们逐字逐句地分析这个脚本。

样板文件

该脚本的第一行是 emacs 模式行。这告诉 emacs 我们在源代码中使用的格式约定(编码风格)

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

模块包含(Module Include)

代码以多个 include 语句开始。

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

命名空间(Namespace)

using namespace ns3;

日志(Logging)

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

主函数(Main Function)

主函数声明

int
main (int argc, char *argv[])
{<!-- -->}

网络配置

基本事件单位和日志配置

下一行将时间分辨率设置为 1 纳秒(nanosecond),这恰好是一个默认值:

Time::SetResolution (Time::NS);

分辨率是可以表示的最小时间值(也是两个时间值之间最小可表示差值)。你只可以更改一次分辨率。启用这种灵活的机制是有点消耗内存的,所以一旦明确设置了分辨率,我们就会释放内存,防止进一步更新(如果不明确设置分辨率,它将默认为 1 纳秒,并且当仿真开始时,内存会被释放)。

脚本接下两行用于启用在 Echo Client 和 Echo Server 应用中内置的两个日志组件:

LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);

这两行代码为 echo 客户端和服务器启用 INFO 级的调试日志记录。这将导致应用在仿真期间,发送和接收数据包时会打印输出日志消息。

现在,我们将直接进入创建拓扑和运行仿真的业务中去。我们使用拓扑助手(topology helper)对象使此工作尽可能的容易。

拓扑助手

节点创建

脚本接下来的两行实际上将创建 ns-3 节点 对象,其代表仿真中的计算机。

NodeContainer nodes;
nodes.Create (2);

它代表一个(我们要给其添加协议栈、应用和外围卡的)计算机。NodeContainer 拓扑助手提供了一个便捷的方法来创建、管理和访问任何 Node 对象。 上面的第一行仅仅声明了一个被称为 nodes 的 NodeContainer。 第二行调用 Node 对象的 Create 方法,要求该 container 创建两个节点。

构建拓扑接下来的一步是将节点连接到一个网络中去。我们支持的最简单的网络形式是两个节点之间的单个点对点链路( point-to-point link)。我们将在这构建一个这样的链路。

点对点通信配置

我们正在构造一个点对点链路,并且在这个对你而言将变得非常熟悉的模式中,我们使用拓扑助手( topology helper)对象来完成将链路放在一起这一低级工作。回想一下,有两个关键抽象分别是 NetDevice 和 Channel。在现实世界中,这些术语大致对应于外围卡和网络线缆。通常,这两个东西紧密地联系在一起,并且不能期望能够互换,如,以太网设备和无线信道。我们的拓扑助手遵循这一紧密耦合,因此你将使用 单独的 PointToPointHelper 来配置和连接 ns-3 的 PointToPointNetDevice 和 PointToPointChannel 对象。

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

第一行,实例化栈上的PointToPointHelper对象。
告诉 PointToPointHelper 对象当它创建一个 PointToPointNetDevice 对象时,使用值为“5Mbps”(每秒 5 兆比特)的**“数据率”(DataRate)**。
从更详细的角度来看,字符串“数据率”相当于我们所谓 PointToPointNetDevice 的 Attribute(属性)
类似于 PointToPointNetDevice 的数据率属性的是 PointToPointChannel “延迟”(Delay)属性 。最后一行,告诉 PointToPointHelper 使用“2ms”(两毫秒)作为(它随后创建的)每个点对点信道的传播延迟(propagation delay)值。

NetDevice配置

此时在脚本中,我们有一个包含两个节点的 NodeContainer。我们有一个 PointToPointHelper,并准备了 PointToPointNetDevices 和 PointToPointChannel 对象。正如在仿真中我们用 NodeContainer 拓扑助手来创建节点,我们将要求 PointToPointHelper 来做这一工作,来创建、配置和安装设备。我们将需要一个所有我们所创建的 NetDevice 对象的列表,所以我们使用 NetDeviceContainer 来保存它们,就像我们使用 NodeContainer来保存我们创建的节点一样。 下面两行代码,

NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);

执行 pointToPoint.Install(nodes) 调用后,我们将有两个节点,每个节点都有一个已安装的点对点 net device,他们之间有一个单独点对点信道。而这两个设备将被配置为在两毫秒传输延迟的信道上以五兆比特每秒的速率传输数据。
不多说,给每个节点安装NetDevice。Ns3认为节点node就是计算机,所以这个install就理解成给计算机装一些必备的硬件就行了。

InternetStack配置

我们现在已经配置了节点和设备,但在节点上并没有安装任何协议栈。接下来的两行代码会处理这个问题。

InternetStackHelper stack;
stack.Install (nodes);

就像 PointToPointHelper 是针对点对点网络设备的,InternetStackHelper 则是针对互联网协议栈的。Install 方法采用 NodeContainer 作为参数。当它被执行时,它将为节点容器中的每个节点安装互联网协议栈(TCP、UDP、IP,等等)。

Ipv4InterfaceContainer interfaces = address.Assign (devices);

执行实际上的地址分配。在 ns-3 中我们使用 IPv4Interface 关联 IP 地址和设备。正如我们有时候需要一列由 helper 创建的 net device 以备后用,我们有时也需要一列 Ipv4Interface 对象。而 Ipv4InterfaceContainer提供了此功能。

我们已经建立了一个点对点网络,安装了协议栈并分配了IP地址。此时我们需要的是产生流量的应用。

IP地址配置

Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = address.Assign (devices);

简单来说,就是配置整个网络地IP地址和子网掩码,节点地IP地址会在这个基础上自动加1.
现在,我们有两个节点,分别是10.1.1.1和10.1.1.2。

应用配置

端口配置

UdpEchoServerHelper echoServer (9);

服务端节点配置

这里第一句话中的参数,nodes是一个容器,有我们的两个节点,get(1)就得到了第一个,意思是第一个节点当做服务器节点。

ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

会导致 echo 服务器应用在 1 秒后开始(启用自身),十秒钟后停止(禁用自身)。基于我们已经声明了一个模拟器事件(应用停止事件)将被执行十秒的事实,模拟器将至少持续十秒的时间。

客户端节点配置

UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));

需要注意的是这里的端口配置,需要和服务器监听的端口号一样,应该不用多说。

后面就是一些物理层或者mac层的配置而已,最大发包数呀,通信间隔呀,包大小之类的。

仿真

   Simulator::Stop (Seconds (11.0));
   Simulator::Run ();
   Simulator::Destroy ();
   return 0;

需要解释一下的是run(),理解为run函数会调用其他的函数,一层一层会进栈,所以destroy函数虽然紧跟着它,但是并不会马上执行,因为run函数没有执行完。

中间的数字可以改,上面表示11s的时候停止,需要写在run前面,进行手动关闭,防止死循环啊之类的。

如果写在run后面,那一旦run进入了死循环,这句话就永远执行不到了,所以后面没有意义。

构建你的脚本

我们已经让构建脚本变得很简单了。你需要做的就是将你的脚本拖到 scratch 目录,然后运行 Waf 它就会自动的被构建好。那么,让我们试试看。在切回顶层目录之后复制 examples/tutorial/first.cc 到 scratch 目录。

$ cd ../..
$ cp examples/tutorial/first.cc scratch/myfirst.cc
$ ./waf
$ ./waf --run scratch/myfirst

运行脚本的结果
这里构建系统先进行检查以确保文件已经生成然后运行它。echo 客户端上的日志记录组件显示它已经发送一个 1024 字节数据包到 10.1.1.2 echo 服务器。echo 服务器上的日志记录组件说它已经从 10.1.1.1 接收到 1024 个字节。echo 服务器静静地 echo 数据包,echo 客户端日志记录到它已经收到了服务器返回的数据包。

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
"ns3 first.cc" 可能是一个IT类问题,它可能指的是使用ns-3网络仿真器创建的第一个C++程序。如果是这样,下面是一些参考答案: ns-3是一个用于网络仿真的开源C++库。 "ns3 first.cc" 可能指的是创建ns-3程序的第一个源代码文件。下面是一个简单的示例程序,用于在ns-3中创建一个简单的网络拓扑,并演示如何在拓扑中发送和接收数据包。 ```c++ #include "ns3/core-module.h" #include "ns3/network-module.h" #include "ns3/internet-module.h" #include "ns3/point-to-point-module.h" using namespace ns3; NS_LOG_COMPONENT_DEFINE ("FirstScriptExample"); int main (int argc, char *argv[]) { Time::SetResolution (Time::NS); LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO); LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO); NodeContainer nodes; nodes.Create (2); PointToPointHelper pointToPoint; pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); NetDeviceContainer devices; devices = pointToPoint.Install (nodes); InternetStackHelper stack; stack.Install (nodes); Ipv4AddressHelper address; address.SetBase ("10.1.1.0", "255.255.255.0"); Ipv4InterfaceContainer interfaces = address.Assign (devices); UdpEchoServerHelper echoServer (9); ApplicationContainer serverApps = echoServer.Install (nodes.Get (1)); serverApps.Start (Seconds (1.0)); serverApps.Stop (Seconds (10.0)); UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9); echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); ApplicationContainer clientApps = echoClient.Install (nodes.Get (0)); clientApps.Start (Seconds (2.0)); clientApps.Stop (Seconds (10.0)); Simulator::Run (); Simulator::Destroy (); return 0; } ``` 这个程序创建了两个节点,将它们连接在一起,并在其中一个节点上启动一个UDP echo服务器,然后在另一个节点上启动一个UDP echo客户端。在客户端上,它向服务器发送一个数据包,服务器将接收它并将其回显回去。这个程序可以通过编译器编译并在ns-3中运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值