ns3中应用如何开始和结束

写在前面的话:

    近来项目需要仿真,开始接触ns3,三周有余,前前后后笔记做了二三十页。由于资料全是英文的,所以笔记也都是英文手稿,而且相当杂乱。所以想着整理下顺便弄成中文的好日后温习。思来想去,还是在csdn上记录下比较好,一来不怕丢,二来说不定能给他人带来点启发,顺便接受点意见,何乐不为。今天看了下应用调用流程,从这儿开始记吧,之前的有空再整理。

 

本篇信息主要来源ns3-tutorial

 

我们在main函数中看到的

ApplicationContainer apps=...;
apps.Start(0);
apps.Stop(10);

三句代码,调用了ApplicationContainer的Start和Stop方法,并传入两个参数startTime和stopTime。ApplicationContainer所做的就是遍历容器中的应用,分别调用

app->SetStartTime(startTime);

功能为设置应用的m_startTime值。

以及

app->SetStopTime(stopTime);

功能为设置应用的m_stopTime值。

可见这里只是设置了两个变量值,并不能解答所提出的问题

要了解应用的调用背后的流程,得从全局的NodeList说起

当我们在模拟器中添加一个Node的时候,模拟器会自动的将一个指向该Node的指针保存到一个全局的NodeList中。具体实现为调用方法:

NodeList::Add

在该函数中会调用实现函数

NodeListPriv::Add

进入到该函数中,发现关键语句

Simulator::ScheduleWithContext(index,TimeStep(0),&Node::Initialize,node);

并不是说在仿真时间0的时候让node做什么。可以理解为一种单纯的通知机制:在仿真时间0的时候,通知相关的node,模拟器已经启动了。

值得注意的是,该函数中调用了Node::Initialize函数,但是在node.h中并没有该函数,于是查看node父类object的Initialize函数

进入到Object::Initialize函数

Object::Initialize (void)
{
  NS_LOG_FUNCTION (this);
restart:
  uint32_t n = m_aggregates->n;
  for (uint32_t i = 0; i < n; i++)
    {
      Object *current = m_aggregates->buffer[i];
      if (!current->m_initialized)
        {
          current->DoInitialize ();
          current->m_initialized = true;
          goto restart;
        }
    }
}

在该函数中有个循环,重点在于循环中的这句

current->DoInitialize ();

也就是说该循环顺序调用了聚合(aggregation)在一起的object的DoInitialize ()函数。所以我们回过头看Node::DoInitialize( )函数

进入到Node::DoInitialize( )

void 
Node::DoInitialize (void)
{
  NS_LOG_FUNCTION (this);
  for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
       i != m_devices.end (); i++)
    {
      Ptr<NetDevice> device = *i;
      device->Initialize ();
    }
  for (std::vector<Ptr<Application> >::iterator i = m_applications.begin ();
       i != m_applications.end (); i++)
    {
      Ptr<Application> application = *i;
      application->Initialize ();
    }

  Object::DoInitialize ();
}

很容易发现,在其中的两个循环中,分别依次调用了绑定在该node上的device以及application的Initialize ( )函数。

由于device和app都继承自object类,所以app的Initialize函数必然也是间接调用了Application::DoInitialize,直接去看Application::DoInitialize( )做了什么。
进入到Application::DoInitialize( )

void
Application::DoInitialize(void)
{
  m_startEvent=Simulator::Schedule(m_startTime,&Application::StartApplication,this);
  if(m_stopTime!=TimeStep(0))
  {
    m_stopEvent=Simulator::Schedule(m_stopTime,&Application::StopApplication,this);
  }
  Object::DoInitialize();
}

可见,最终功能便是调用Simulator::Schedule在仿真队列中“安排”了开始和结束两个事件。在安排这两个事件时,分别回调了Application::StartApplication以及Application::StopApplication两个函数。这也正是我们添加自己的app需要重写的两个方法。

至此,ns3中应用的启动停止原理已经解释清楚。并且我们在添加自己的app时改写的两个方法是如何工作的也已经说清楚。



 


 

 

 

 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里给您提供一个简单的NS-3仿真代码示例: ```c++ #include "ns3/core-module.h" #include "ns3/network-module.h" #include "ns3/internet-module.h" #include "ns3/applications-module.h" using namespace ns3; NS_LOG_COMPONENT_DEFINE ("FirstNS3Script"); int main (int argc, char *argv[]) { // 初始化日志记录 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); // 分配IP地址 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回显服务器应用程序和一个UDP回显客户端应用程序,以测试连接是否正常工作。在仿真期间,客户端应用程序将向服务器应用程序发送一个数据包,并在1秒内等待服务器应用程序响应。仿真器将运行10秒钟,最终结束

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值