【网络仿真】ns-3基础(下)

6 ns-3其他模块

6.1 网络模块

分组:传递的消息,模拟器基本对象。ns-3中每个分组包括一个字节缓冲区和一个Tag列表,通过Header类和Trailer类对缓冲区数据进行添加和删除。

6.1.1 分组

请添加图片描述

6.1.3 分组接口

分组对象的公共成员函数

// 1. 构造函数
Packet();//用新的uid创建一个空分组,返回getuid
Packet(uint32_t size);//size为0填充的有效载荷大小
// 2. 添加或删除缓冲区数据
void Add (Header const &header);// 为分组添加报头,调用了ns3::Header::serializeTo()为报头在数据分组缓冲区本身序列化。
void Peek (Header &header);
void Remove (Header const &header);
// 3. 添加或删除标签Tags到分组
template <typename T> // 定义一个模板,template为模板关键字。<>内为参数列表,此处使用的是类型参数,用typename声明。T可以使得函数在调用时决定是什么类型(避免写过多的重载函数)。
void AddTag (T const &tag);// 提高代码效率,声明为常量的引用

template <typename T>
bool RemoveTag (T &tag); // 从分组中删除标签

template <typename T>
bool PeekTag (T &tag) const; // 复制一个存储到内部的标签,如果没有这个标签的实例,则输入标签将不会被更改。 

void RemoveAllTags (void);// 删除所有存储在这个数据分组中的标签。比removeTag快。

// 4. 分组Fragmentation
Packet CreateFragment (uint32_t start, uint32_t length) const; // 创建一个新的数据分组,其中包含一个原始数据分组片段。返回的数据分组共享相同的uid。
void addAtEnd (Packet packet); // 将输入数据分组连接到当前数据分组的尾部。
void AddAtEnd (Packet packet, uint32_t offset, uint32_t size); // 输入偏移量和尺寸参数。
void RemoveAtEnd (uint32_t size);
void RemoveAtStart (uint32_t size);

// 5. 其他Miscellaneous
uint32_t GetSize (void) const; // 返回数据分组大小的字节
uint8_t const *PeekData (void) const; //返回指向数据分组内部缓冲区的指针
uint32_t GetUid (void) const;

6.1.4 实例程序

  1. src/network/examples/main-packet-header.cc
# include "ns3/ptr.h"
# include "ns3/packet.h"
# include "ns3/header.h"
# include <iostream>
using namespace std;

// 报头实例定义
class MyHeader : public Header
{
	public:
		MyHeader (); // 构造函数声明
		virtual ~MyHeader (); // 析构函数声明
		void SetData (uint16_t data);
		uint16_t GetData (void) const;

		static TypeId GetTypeId (void);
		
		virtual TypeId 
}

// 成员函数定义
 
  1. src/network/examples/main-packet-tag.cc

6.1.5 实现细节

6.2 Internet模块

6.2.1 Internet协议栈

源代码:src/Internet中

// 为节点添加协议栈(在分配IP地址之前)
InternetStackHelper stack;
stack.Install (nodes);

包括两层的协议组件:

  1. Layer-3 protocols
    IPv4L3Protocol类
  2. Layer-4 protocols

6.2.2 路由

6.2.3 TCP

6.3 网络设备模块

6.3.1 PointToPoint 点到点

6.3.2 CSMA 有线局域网

6.3.3 Wi-Fi 无线局域网

6.4 应用层模块

Application类:所有应用程序的基类,在src/network/model/application.h和application.cc中。

有多种应用程序:

  1. UdpClientServer 应用
  • 基于UDP的应用程序。此模块有4个类:SeqTsHeader类(设置、获取UDP协议分组的头)、UdpClient类(配置客户端)、UdpServer类(配置服务器端)和UdpTraceClient类(与UdpClient类相似,但UdpTraceClient类使用的是指定文件作为数据流,UdpClient类使用系统自动给出的数据流)。

  • 用户直接使用的是Helper类,其头文件:udp-client-server-helper.h和udp-client-server-helper.cc,源代码:ns-3.xx/src/applications/helper

  • 例子:ns-3.xx/examples/udp-client-server/udp-client-server.cc

// Network topology
//
//       n0    n1
//       |     |
//       =======
//         LAN (CSMA)
//
// - UDP flow from n0 to n1 of 1024 byte packets at intervals of 50 ms 在50ms内,节点n0给n1发1024字节的数据包
//   - maximum of 320 packets sent (or limited by simulation duration)
//   - option to use IPv4 or IPv6 addressing
//   - option to disable logging statements

#include <fstream>
#include "ns3/core-module.h"
#include "ns3/csma-module.h"
#include "ns3/applications-module.h"
#include "ns3/internet-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("UdpClientServerExample");

int
main (int argc, char *argv[])
{
  // Declare variables used in command-line arguments 使用命令行声明变量
  bool useV6 = false;
  bool logging = true;
  Address serverAddress;

  CommandLine cmd (__FILE__);
  cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
  cmd.AddValue ("logging", "Enable logging", logging);
  cmd.Parse (argc, argv);

  if (logging)
    {
      LogComponentEnable ("UdpClient", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
    }

  NS_LOG_INFO ("Create nodes in above topology.");
  NodeContainer n;
  n.Create (2);

  InternetStackHelper internet;
  internet.Install (n);

  NS_LOG_INFO ("Create channel between the two nodes.");
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
  csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
  NetDeviceContainer d = csma.Install (n);

  NS_LOG_INFO ("Assign IP Addresses.");
  if (useV6 == false)
    {
      Ipv4AddressHelper ipv4;
      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
      Ipv4InterfaceContainer i = ipv4.Assign (d);
      serverAddress = Address (i.GetAddress (1));
    }
  else
    {
      Ipv6AddressHelper ipv6;
      ipv6.SetBase ("2001:0000:f00d:cafe::", Ipv6Prefix (64));
      Ipv6InterfaceContainer i6 = ipv6.Assign (d);
      serverAddress = Address(i6.GetAddress (1,1));
    }

  NS_LOG_INFO ("Create UdpServer application on node 1.");
  uint16_t port = 4000; // 定义无符号16bit变量,命名为端口号,值为4000
  UdpServerHelper server (port); // 创建UdpServerHelper对象,命名为server,参数为port
  ApplicationContainer apps = server.Install (n.Get (1)); // ApplicationContainer Install(NodeConstainer c)函数:将参数中的节点创建一个 UdpClientServer应用程序,并返回一个应用程序容器ApplicationContainer。
  apps.Start (Seconds (1.0)); 
  apps.Stop (Seconds (10.0));

  NS_LOG_INFO ("Create UdpClient application on node 0 to send to node 1.");
  uint32_t MaxPacketSize = 1024;
  Time interPacketInterval = Seconds (0.05);
  uint32_t maxPacketCount = 320;
  UdpClientHelper client (serverAddress, port); //创建UdpClientHelper对象。
  client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
  client.SetAttribute ("Interval", TimeValue (interPacketInterval));
  client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));
  apps = client.Install (n.Get (0));
  apps.Start (Seconds (2.0));
  apps.Stop (Seconds (10.0));

  NS_LOG_INFO ("Run Simulation.");
  Simulator::Run ();
  Simulator::Destroy ();
  NS_LOG_INFO ("Done.");
}

  1. UdpEcho程序
  • Echo应答协议主要用于调试和检测中,即收到什么就原封发回。可以基于TCP协议,也可以使用UDP协议,检测的端口都是7。
  • UdpEcho应用程序是基于UDP,涉及两个类:UdpEchoClient和UdpEchoServer。
  • 对应的helper类:UdpEchoServerHelper和UdpEchoClientHelper。其头文件:udp-echo-helper.h和udp-echo-helper.cc,源代码:ns-3.xx/src/applications/helper
  1. Radvd
  2. Ping6应用程序
  • Ping: 用来检测网络是否通畅或网络连接速度的命令。
  • Ping6应用程序是基于IPv6的。
  • Ping6类:class Ping6, class Ping6Helper
  • 例子:ns-3.xx/examples/ipv6/ping6.cc
// Network topology
//
//       n0    n1
//       |     |
//       =================
//              LAN
//
// - ICMPv6 echo request flows from n0 to n1 and back with ICMPv6 echo reply
// - DropTail queues 
// - Tracing of queues and packet receptions to file "ping6.tr"

#include <fstream>
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-apps-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("Ping6Example");

int main (int argc, char **argv)
{
  bool verbose = false;

  CommandLine cmd (__FILE__);
  cmd.AddValue ("verbose", "turn on log components", verbose);
  cmd.Parse (argc, argv);

  if (verbose)
    {
      LogComponentEnable ("Ping6Example", LOG_LEVEL_INFO);
      LogComponentEnable ("Ipv6EndPointDemux", LOG_LEVEL_ALL);
      LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL);
      LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL);
      LogComponentEnable ("Ipv6ListRouting", LOG_LEVEL_ALL);
      LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
      LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
      LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
      LogComponentEnable ("NdiscCache", LOG_LEVEL_ALL);
    }

  NS_LOG_INFO ("Create nodes.");
  NodeContainer n;
  n.Create (4);

  /* Install IPv4/IPv6 stack */
  InternetStackHelper internetv6;
  internetv6.SetIpv4StackInstall (false);
  internetv6.Install (n);

  NS_LOG_INFO ("Create channels.");
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
  NetDeviceContainer d = csma.Install (n);

  Ipv6AddressHelper ipv6;
  NS_LOG_INFO ("Assign IPv6 Addresses.");
  Ipv6InterfaceContainer i = ipv6.Assign (d);

  NS_LOG_INFO ("Create Applications.");

  /* Create a Ping6 application to send ICMPv6 echo request from node zero to
   * all-nodes (ff02::1).
   */
  uint32_t packetSize = 1024;
  uint32_t maxPacketCount = 5;
  Time interPacketInterval = Seconds (1.);
  Ping6Helper ping6;

  /*
     ping6.SetLocal (i.GetAddress (0, 1)); 
     ping6.SetRemote (i.GetAddress (1, 1));
     */
  ping6.SetIfIndex (i.GetInterfaceIndex (0)); // GetInterfaceIndex(0) 获取IPv6地址中0号节点地址作为ping程序的运行主机。
  ping6.SetRemote (Ipv6Address::GetAllNodesMulticast ()); // GetAllNodesMulticast ()获取所有主机的IP。ping6.SetRemote()设置Ping命令的参数,参数为局域网内所有PC。

  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
  ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
  ApplicationContainer apps = ping6.Install (n.Get (0));
  apps.Start (Seconds (2.0));
  apps.Stop (Seconds (10.0));

  AsciiTraceHelper ascii;
  csma.EnableAsciiAll (ascii.CreateFileStream ("ping6.tr"));
  csma.EnablePcapAll (std::string ("ping6"), true);

  NS_LOG_INFO ("Run Simulation.");
  Simulator::Run ();
  Simulator::Destroy ();
  NS_LOG_INFO ("Done.");
}



  1. PacketSink模块:接收数据包
  2. OnOffApplication
  3. BulkSendApplication
    学习方法:先看类及其Helper的定义API (ns-3.xx/src中,看.h文件了解类的成员函数输入输出即可)->再看例子,了解脚本程序中如何使用(ns-3.xx/examples中)。

例子1:ns-3.xx/examples/tcp/tcp-star-sever.cc。使用了PacketSink和OnOffApplication模块。

// Default Network topology, 9 nodes in a star
/*
          n2 n3 n4
           \ | /
            \|/
       n1---n0---n5
            /| \
           / | \
          n8 n7 n6
*/
// - CBR Traffic goes from the star "arms" to the "hub"
// - Tracing of queues and packet receptions to file
//   "tcp-star-server.tr"
// - pcap traces also generated in the following files
//   "tcp-star-server-$n-$i.pcap" where n and i represent node and interface numbers respectively
// Usage examples for things you might want to tweak:
//       ./waf --run="tcp-star-server"
//       ./waf --run="tcp-star-server --nNodes=25"
//       ./waf --run="tcp-star-server --ns3::OnOffApplication::DataRate=10000"
//       ./waf --run="tcp-star-server --ns3::OnOffApplication::PacketSize=500"
// See the ns-3 tutorial for more info on the command line: 
// http://www.nsnam.org/tutorials.html




#include <iostream>
#include <fstream>
#include <string>
#include <cassert>

#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"
#include "ns3/ipv4-global-routing-helper.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("TcpServer");

int 
main (int argc, char *argv[])
{
  // Users may find it convenient to turn on explicit debugging
  // for selected modules; the below lines suggest how to do this

  //LogComponentEnable ("TcpServer", LOG_LEVEL_INFO);
  //LogComponentEnable ("TcpL4Protocol", LOG_LEVEL_ALL);
  //LogComponentEnable ("TcpSocketImpl", LOG_LEVEL_ALL);
  //LogComponentEnable ("PacketSink", LOG_LEVEL_ALL);

  // Set up some default values for the simulation.
  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (250));
  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("5kb/s"));
  uint32_t N = 9; //number of nodes in the star

  // Allow the user to override any of the defaults and the above
  // Config::SetDefault()s at run-time, via command-line arguments
  CommandLine cmd (__FILE__);
  cmd.AddValue ("nNodes", "Number of nodes to place in the star", N);
  cmd.Parse (argc, argv);

  // Here, we will create N nodes in a star.
  NS_LOG_INFO ("Create nodes.");
  NodeContainer serverNode;
  NodeContainer clientNodes;
  serverNode.Create (1);
  clientNodes.Create (N-1);
  NodeContainer allNodes = NodeContainer (serverNode, clientNodes);

  // Install network stacks on the nodes
  InternetStackHelper internet;
  internet.Install (allNodes);

  //Collect an adjacency list of nodes for the p2p topology
  std::vector<NodeContainer> nodeAdjacencyList (N-1);
  for(uint32_t i=0; i<nodeAdjacencyList.size (); ++i)
    {
      nodeAdjacencyList[i] = NodeContainer (serverNode, clientNodes.Get (i));
    }

  // We create the channels first without any IP addressing information
  NS_LOG_INFO ("Create channels.");
  PointToPointHelper p2p;
  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
  std::vector<NetDeviceContainer> deviceAdjacencyList (N-1);
  for(uint32_t i=0; i<deviceAdjacencyList.size (); ++i)
    {
      deviceAdjacencyList[i] = p2p.Install (nodeAdjacencyList[i]);
    }

  // Later, we add IP addresses.
  NS_LOG_INFO ("Assign IP Addresses.");
  Ipv4AddressHelper ipv4;
  std::vector<Ipv4InterfaceContainer> interfaceAdjacencyList (N-1);
  for(uint32_t i=0; i<interfaceAdjacencyList.size (); ++i)
    {
      std::ostringstream subnet;
      subnet<<"10.1."<<i+1<<".0";
      ipv4.SetBase (subnet.str ().c_str (), "255.255.255.0");
      interfaceAdjacencyList[i] = ipv4.Assign (deviceAdjacencyList[i]);
    }

  //Turn on global static routing
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  // Create a packet sink on the star "hub" to receive these packets
  uint16_t port = 50000;
  Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress); // 使用构造函数为中心节点hub创建应用程序,第一个参数为协议,第二个参数为IP地址。
  ApplicationContainer sinkApp = sinkHelper.Install (serverNode);
  sinkApp.Start (Seconds (1.0));
  sinkApp.Stop (Seconds (10.0));

  // Create the OnOff applications to send TCP to the server
  OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ());
  clientHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
  clientHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));

  //normally wouldn't need a loop here but the server IP address is different
  //on each p2p subnet
  ApplicationContainer clientApps;
  for(uint32_t i=0; i<clientNodes.GetN (); ++i)
    {
      AddressValue remoteAddress
        (InetSocketAddress (interfaceAdjacencyList[i].GetAddress (0), port));
      clientHelper.SetAttribute ("Remote", remoteAddress);
      clientApps.Add (clientHelper.Install (clientNodes.Get (i)));
    }
  clientApps.Start (Seconds (1.0));
  clientApps.Stop (Seconds (10.0));


  //configure tracing
  AsciiTraceHelper ascii;
  p2p.EnableAsciiAll (ascii.CreateFileStream ("tcp-star-server.tr"));
  p2p.EnablePcapAll ("tcp-star-server");

  NS_LOG_INFO ("Run Simulation.");
  Simulator::Run ();
  Simulator::Destroy ();
  NS_LOG_INFO ("Done.");

  return 0;
}

例子2:ns-3.xx/examples/tcp/tcp-bukl-send.cc。使用了PacketSink和 BulkSendApplication模块。

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

// Network topology
//
//       n0 ----------- n1
//            500 Kbps
//             5 ms
//
// - Flow from n0 to n1 using BulkSendApplication.
// - Tracing of queues and packet receptions to file "tcp-bulk-send.tr"
//   and pcap tracing available when tracing is turned on.

#include <string>
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/internet-module.h"
#include "ns3/applications-module.h"
#include "ns3/network-module.h"
#include "ns3/packet-sink.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("TcpBulkSendExample");

int
main (int argc, char *argv[])
{

  bool tracing = false;
  uint32_t maxBytes = 0;

//
// Allow the user to override any of the defaults at
// run-time, via command-line arguments
//
  CommandLine cmd (__FILE__);
  cmd.AddValue ("tracing", "Flag to enable/disable tracing", tracing);
  cmd.AddValue ("maxBytes",
                "Total number of bytes for application to send", maxBytes);
  cmd.Parse (argc, argv);

//
// Explicitly create the nodes required by the topology (shown above).
//
  NS_LOG_INFO ("Create nodes.");
  NodeContainer nodes;
  nodes.Create (2);

  NS_LOG_INFO ("Create channels.");

//
// Explicitly create the point-to-point link required by the topology (shown above).
//
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("500Kbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("5ms"));

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

//
// Install the internet stack on the nodes
//
  InternetStackHelper internet;
  internet.Install (nodes);

//
// We've got the "hardware" in place.  Now we need to add IP addresses.
//
  NS_LOG_INFO ("Assign IP Addresses.");
  Ipv4AddressHelper ipv4;
  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer i = ipv4.Assign (devices);

  NS_LOG_INFO ("Create Applications.");

//
// Create a BulkSendApplication and install it on node 0
//
  uint16_t port = 9;  // well-known echo port number


  BulkSendHelper source ("ns3::TcpSocketFactory",
                         InetSocketAddress (i.GetAddress (1), port));
  // Set the amount of data to send in bytes.  Zero is unlimited.
  source.SetAttribute ("MaxBytes", UintegerValue (maxBytes));
  ApplicationContainer sourceApps = source.Install (nodes.Get (0));
  sourceApps.Start (Seconds (0.0));
  sourceApps.Stop (Seconds (10.0));

//
// Create a PacketSinkApplication and install it on node 1
//
  PacketSinkHelper sink ("ns3::TcpSocketFactory",
                         InetSocketAddress (Ipv4Address::GetAny (), port));
  ApplicationContainer sinkApps = sink.Install (nodes.Get (1));
  sinkApps.Start (Seconds (0.0));
  sinkApps.Stop (Seconds (10.0));

//
// Set up tracing if enabled
//
  if (tracing)
    {
      AsciiTraceHelper ascii;
      pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("tcp-bulk-send.tr"));
      pointToPoint.EnablePcapAll ("tcp-bulk-send", false);
    }

//
// Now, do the actual simulation.
//
  NS_LOG_INFO ("Run Simulation.");
  Simulator::Stop (Seconds (10.0));
  Simulator::Run ();
  Simulator::Destroy ();
  NS_LOG_INFO ("Done.");

  Ptr<PacketSink> sink1 = DynamicCast<PacketSink> (sinkApps.Get (0));
  std::cout << "Total Bytes Received: " << sink1->GetTotalRx () << std::endl;
}

6.5 移动模块

  • 在ns-3中移动模型集成在可移动节点中,可使用GetObject<MobilityModel>()从已绑定模型的节点中提取移动模型。
  • 所有的移动模型都是继承ns3::MobilityModel类。
  • 移动节点初始位置分布由PositionAllocator类负责。
  • MobileHelper类把移动模型和位置分配整合在一起,从而方便为Node节点安装移动模型。
  • ns3::Vector类是坐标系统的基类。

ns3::MobilityModel类

  • 所有移动模型的基类。追踪物体目前的位置(m)和速度(m/s)
  • 定义在src/mobility/model/mobility-model.h中
#ifndef MOBILITY_MODEL_H
#define MOBILITY_MODEL_H

#include "ns3/vector.h"
#include "ns3/object.h"
#include "ns3/traced-callback.h"

namespace ns3 {
class MobilityModel : public Object
{
public:
  /**
   * Register this type with the TypeId system.
   * \return the object TypeId
   */
  static TypeId GetTypeId (void);
  MobilityModel ();
  virtual ~MobilityModel () = 0;

  /**
   * \return the current position
   */
  Vector GetPosition (void) const;
  /**
   * \param position the position to set.
   */
  void SetPosition (const Vector &position);
  /**
   * \return the current velocity.
   */
  Vector GetVelocity (void) const;
  /**
   * \param position a reference to another mobility model
   * \return the distance between the two objects. Unit is meters.
   */
  double GetDistanceFrom (Ptr<const MobilityModel> position) const;
  /**
   * \param other reference to another object's mobility model
   * \return the relative speed between the two objects. Unit is meters/s.
   */
  double GetRelativeSpeed (Ptr<const MobilityModel> other) const;
  /**
   * Assign a fixed random variable stream number to the random variables
   * used by this model. Return the number of streams (possibly zero) that
   * have been assigned.
   *
   * \param stream first stream index to use
   * \return the number of stream indices assigned by this model
   */
  int64_t AssignStreams (int64_t stream);

  /**
   *  TracedCallback signature.
   *
   * \param [in] model Value of the MobilityModel.
   */
  typedef void (* TracedCallback)(Ptr<const MobilityModel> model);
  
protected:
  /**
   * Must be invoked by subclasses when the course of the
   * position changes to notify course change listeners.
   */
  void NotifyCourseChange (void) const;
private:
  /**
   * \return the current position.
   *
   * Concrete subclasses of this base class must 
   * implement this method.
   */
  virtual Vector DoGetPosition (void) const = 0;
  /**
   * \param position the position to set.
   *
   * Concrete subclasses of this base class must 
   * implement this method.
   */
  virtual void DoSetPosition (const Vector &position) = 0;
  /**
   * \return the current velocity.
   *
   * Concrete subclasses of this base class must 
   * implement this method.
   */
  virtual Vector DoGetVelocity (void) const = 0;
  /**
   * The default implementation does nothing but return the passed-in
   * parameter.  Subclasses using random variables are expected to
   * override this.
   * \param start  starting stream index
   * \return the number of streams used
   */
  virtual int64_t DoAssignStreams (int64_t start);

  /**
   * Used to alert subscribers that a change in direction, velocity,
   * or position has occurred.
   */
  ns3::TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;

};

} // namespace ns3

#endif /* MOBILITY_MODEL_H */

移动模型的使用。
例子1:third.cc

  MobilityHelper mobility; // 用MobilityHelper类声明对象mobility
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator", // 设置初始位置的方案。包括:ListPositionAllocator(自定义节点的初始位置列表)、GridPositionAllocator(根据表格形式为节点初始化位置)、RandomRectanglePositionAllocator(给出随机矩阵初始化节点位置)、RandomBoxPositionAllocator(给出一个随机立体矩形分配方案)
                                 "MinX", DoubleValue (0.0),
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (5.0),
                                 "DeltaY", DoubleValue (10.0),
                                 "GridWidth", UintegerValue (3),
                                 "LayoutType", StringValue ("RowFirst")); // 调用SetPositionAllocator()函数初始化节点的初始位置

  mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
                             "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50))); // 调用SetMobilityModel()设置要使用的移动模型
  mobility.Install (wifiStaNodes); // 将准备好的移动模型安装到每一个节点上

  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (wifiApNode);

例子2: src/mobility/examples/main-random-walk.cc

6.6 能量模块

现实中,无线设备会消耗能量。仿真中,需要确定节点或网络的能量消耗,因此需要ns-3对能量消耗建模。

6.6.1 模型描述

ns-3能量模块由两部分组成:能量资源(电池、煤气)、设备能量模型(每个设备有多种状态,每个状态带有一个功耗值)。

6.6.2 用法

与ns-3能量模块交互:通过助手API和公开的模块属性。
使用模块先为节点安装能量资源,为网络设备安装相应的设备能量模型。
例子:src/examples/energy和examples/energy。

  1. 助手

  2. 属性

  3. 跟踪

  4. 验证

6.6.3 示例

  • ns-3.xx/src/energy/examples/li-ion-energy-source.cc
/*
 * Author: Andrea Sacco <andrea.sacco85@gmail.com>
 */

#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/command-line.h"
#include "ns3/simple-device-energy-model.h"
#include "ns3/li-ion-energy-source.h"
#include "ns3/energy-source-container.h"

using namespace ns3;

/**
 * In this simple example, we show how to create and drain energy from a
 * LiIonEnergySource. 锂离子能源的创建和消耗
 * We make a series of discharge calls to the energy source class with
 * different current drain and duration until all the energy is depleted
 * from the cell. 我们对具有不同电流消耗和持续时间的能源类进行一系列放电调用,直到所有能量从电池中耗尽
 *
 * Every 20 seconds it is printed out the actual cell voltage to verify
 * that it follows the discharge curve of the datasheet [1]. 每20s打印电池电压,证明符合数据表1的放电曲线
 *
 * At the end of the example it is verified that after the energy depletion
 * call, the cell voltage is below the threshold voltage. 电压低于阈值时,能量停止调用
 *
 * References:
 * [1] Panasonic CGR18650DA Datasheet, http://www.panasonic.com/industrial/includes/pdf/Panasonic_LiIon_CGR18650DA.pdf
 */

static void
PrintCellInfo (Ptr<LiIonEnergySource> es)
{
  std::cout << "At " << Simulator::Now ().As (Time::S) << " Cell voltage: " << es->GetSupplyVoltage () << " V Remaining Capacity: " <<
  es->GetRemainingEnergy () / (3.6 * 3600) << " Ah" << std::endl;

  if (!Simulator::IsFinished ())
    {
      Simulator::Schedule (Seconds (20),
                           &PrintCellInfo,
                           es);
    }
}

int
main (int argc, char **argv)
{
  CommandLine cmd (__FILE__);
  cmd.Parse (argc, argv);
  
    // uncomment below to see the energy consumption details
  // LogComponentEnable ("LiIonEnergySource", LOG_LEVEL_DEBUG);

  Ptr<Node> node = CreateObject<Node> (); // 生成节点

  Ptr<SimpleDeviceEnergyModel> sem = CreateObject<SimpleDeviceEnergyModel> ();
  Ptr<EnergySourceContainer> esCont = CreateObject<EnergySourceContainer> ();
  Ptr<LiIonEnergySource> es = CreateObject<LiIonEnergySource> ();
  esCont->Add (es);
  es->SetNode (node);
  sem->SetEnergySource (es);
  es->AppendDeviceEnergyModel (sem);
  sem->SetNode (node);
  node->AggregateObject (esCont);

  Time now = Simulator::Now ();

  // discharge at 2.33 A for 1700 seconds
  sem->SetCurrentA (2.33);
  now += Seconds (1701);


  // discharge at 4.66 A for 628 seconds
  Simulator::Schedule (now,
                       &SimpleDeviceEnergyModel::SetCurrentA,
                       sem,
                       4.66);
  now += Seconds (600);

  PrintCellInfo (es);

  Simulator::Stop (now);
  Simulator::Run ();
  Simulator::Destroy ();

  // the cell voltage should be under 3.3v
  DoubleValue v;
  es->GetAttribute ("ThresholdVoltage", v);
  NS_ASSERT (es->GetSupplyVoltage () <= v.Get ());
}

# 运行
./waf --run li-ion-energy-source
# 结果
At 0 Cell voltage : 4.05 V Remaining Capacity : 2.45 Ah
...

6.7 添加模块

6.7.1 生成新模块

6.7.2 添加新模块

7 示例

7.1 first.cc

位置:ns-3.xx/examples/tutorial/

//0. Emacs模式行,解释代码的预定格式(GNU,General Public License许可)
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
//1.头文件
#include "ns3/core-module.h" //all header file is at build/ns3
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/netanim-module.h"
// 在两个节点间创建一个简单的点到点通信
// Default Network Topology
//
//       10.1.1.0
// n0 -------------- n1
//    point-to-point
//

//2.命名空间
using namespace ns3; //if is not at namespace ns3, add xx:: ,e.g. Time::NS, std::cout, std::min()

//3.定义日志LOG模块(允许脚本使用log系统中的宏定义打印辅助信息)
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

//4.主函数
int
main (int argc, char *argv[])
{
  CommandLine cmd;//在命令行中可以输入参数,例如sudo ./waf --run "hello-simulator --numbers=5"
  cmd.Parse (argc, argv);//读取命令行参数
  
  Time::SetResolution (Time::NS);//最小单元时间,毫秒
  //将”UdpEcho”应用程序的客户端和服务器端日志级别设为”INFO”级。即当仿真产生数据分组发送和接收时,对应应用就会输出相应的日志消息到相关的日志模块。
  LogComponentEnable ("UdpEchoClientApplication",LOG_LEVEL_INFO); 
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

  //5.创建网络拓扑
  NodeContainer nodes; 
  nodes.Create (2); //创建两个网络节点,访问:nodes.Get (0)、 nodes.Get (1)

  PointToPointHelper pointToPoint; //创建p2p助手类
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));//设置设备属性——设备的传输速率
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
  NetDeviceContainer devices;//创建网络设备
  devices = pointToPoint.Install (nodes);// pointToPoint.Install (nodes)函数创建了两个p2p网络设备对象也一个p2p信道对象,并将它们连接一块。

  //6. 安装TCP/IP协议栈
  InternetStackHelper stack;
  stack.Install (nodes);//为nodes容器中的节点安装TCP/IP协议栈,主要是IP层

  Ipv4AddressHelper address;//为网络设备分配IP地址,拓扑助手管理IP地址的分配
  address.SetBase ("10.1.1.0", "255.255.255.0");//设置起始地址,子网掩码

  Ipv4InterfaceContainer interfaces = address.Assign (devices);//把生成的ip地址分配给每个设备(地址从1开始,单调递增,即10.1.1.1、10.1.1.2)

  //7. 安装应用程序
//服务器端
  UdpEchoServerHelper echoServer (9);//服务端监听端口为9

  ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));// echoServer.Install()方法把echoServer 应用安装在1号节点,并用ApplicationContainer记录
  serverApps.Start (Seconds (1.0));//设置application在第1s开始运行
  serverApps.Stop (Seconds (10.0));//第10s结束
//客户端
  UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);//客户端助手类UdpEchoClientHelper在0号节点创建应用echoClient,属性:连接到1号ip地址和端口
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));//模拟期间,可发送的最大分组个数1
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0))); //分组发送间隔1s
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));//分组负载字节大小,1024bit

  ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));//模拟启动后2s节点0向节点1的9号端口发一个1024bit的UDP数据包,第10s结束

  //this is set for visualization (NetAnim)
  AnimationInterface anim("first.xml");
  anim.SetConstantPosition(nodes.Get(0), 1.0, 2.0);
  anim.SetConstantPosition(nodes.Get(1), 2.0, 3.0);
  
  //8. 启动与结束
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

7.2 second.cc

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
// 运行指令,在ns-3.29下
// cp examples/tutorial/second.cc scratch/second.cc
// ./waf --run second
// ./waf --run second --vis # 可视化
// ./waf --run “second -- nCsma=100” --vis # 局域网中节点数3->101

//1.头文件
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"
//仿真拓扑图,有两种网络:p2p网络和CSMA网络,分别有2个和4个节点。其中n1上安装有两种NetDevice,i.e. p2p和csma。n0通过n1与n4通信。
// Default Network Topology
//
//       10.1.1.0
// n0 -------------- n1   n2   n3   n4
//    point-to-point  |    |    |    |
//                    ================
//                      LAN 10.1.2.0

//2.命名空间
using namespace ns3;

//3.定义LOG模块
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");

//4.主函数
int 
main (int argc, char *argv[])
{
  bool verbose = true;//定义变量,决定是否开启2个applications的logging组件;默认true开启
  uint32_t nCsma = 3;//LAN中另外有3个node

  //使用命令行声明nCsma变量
  CommandLine cmd;
  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);//添加命令行参数。nCsma变量表示,CSMA节点数目
  cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);

  cmd.Parse (argc,argv);//读取命令行参数

  if (verbose)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);  //打印UdpEchoClientApplication组件信息
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO); //打印UdpEchoServerApplication组件信息
    }

  nCsma = nCsma == 0 ? 1 : nCsma;
  //5.创建网络拓扑
  NodeContainer p2pNodes;
  p2pNodes.Create (2);//创建两个p2p型节点,n0----n1

  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));//n1节点既是p2p节点,又是csma节点
  csmaNodes.Create (nCsma);//创建额外的nCsma个csma节点,n2,n3,n4

  PointToPointHelper pointToPoint;//p2p助手类,设置设备和信道属性
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));//设置设备传输速率为5Mbps
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));//设置信道延迟为2ms

  NetDeviceContainer p2pDevices; //创建p2p网络设备
  p2pDevices = pointToPoint.Install (p2pNodes); //把p2p网络设备分别安装在节点n0和n1上,然后共同连接至同一信道对象

  CsmaHelper csma;//csma助手类,设置csma信道属性
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));//设置传输速率为100Mbps
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));//设置信道延迟为6560ns

  NetDeviceContainer csmaDevices;//创建csma网络设备
  csmaDevices = csma.Install (csmaNodes);//连接节点与信道

  //6.安装协议栈和分配ip地址
  
  InternetStackHelper stack;//为每个节点安装协议栈
  stack.Install (p2pNodes.Get (0));
  stack.Install (csmaNodes);

  Ipv4AddressHelper address; 
  address.SetBase ("10.1.1.0", "255.255.255.0");//为p2p网络设备分配ip地址,起始地址为10.1.1.0,终止地址为10.1.1.254
  Ipv4InterfaceContainer p2pInterfaces;
  p2pInterfaces = address.Assign (p2pDevices);

  address.SetBase ("10.1.2.0", "255.255.255.0");//为csma网络设备分配ip地址,起始地址为10.1.2.0,终止地址为10.1.2.254
  Ipv4InterfaceContainer csmaInterfaces;
  csmaInterfaces = address.Assign (csmaDevices);
  
  //7.安装应用程序
  UdpEchoServerHelper echoServer (9);//监听9号端口
 //配置服务端属性
  ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));//使用Install方法将echoServer安装在节点n4(n3?)上,application在第1s开始运行并接受9号端口数据,在第10s结束。
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (10.0));
 //配置客户端属性
  UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));//最大发送分组个数,1
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));//分组发送间隔1s
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));//数据包大小,1024bit

  ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));//使用install方法将echoClient安装在节点n0上。Application在模拟,第2s开始运行,并接受9号端口的数据,在第10s停止。
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));

//8.设置全局路由
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
//9.数据追踪
//开启P2PHelper类对象的pacp,second为保存文件的前缀名。
  pointToPoint.EnablePcapAll ("second");//EnablePcapAll (“second”)函数的作用是收集这个信道上所有结点链路层分组收发记录。记录文件格式是pcap,”second”是文件名前缀。
//开启csmaHelper类对象的pcap,使用CSMA网段索引为1的设备(第二个)进行sniff,True开启Promiscuous mode
  csma.EnablePcap ("second", csmaDevices.Get (1), true);//记录了一个有线节点中CSMA网络设备的分组收发信息
//10.启动与结束
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

运行后上层文件产生3个跟踪文件:
请添加图片描述
在这里插入图片描述

second-0-0.pcap表示点到点网络设备上节点0、设备0的跟踪文件。查看其文件内容:

# 命令
tcpdump -nn -tt -r second-0-0.pcap
# 输出
reading from file second-0-0.pcap, link-type PPP (PPP) # 链路类型为PPP
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 # 数据分组从节点0(IP:10.1.1.1, port:49153)发出,到达节点4(IP:10.1.2.4, port:9)
2.007607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024 

# 命令
tcpdump -nn -tt -r second-2-0.pcap 
# 输出
reading from file second-2-0.pcap, link-type EN10MB (Ethernet) # 链路类型为以太网,需要ARP地址解析协议
2.003698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50 # 先在CSMA网络(ff:ff:ff:ff:ff:ff)广播找IP为10.1.2.4的设备 (节点2不直接参与交流,但嗅探网络并报告所有流量)
2.003710 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50
2.003803 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.003815 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50 # 服务器给客户端回话,知道其地址在另一个网络(IP:10.1.2.1)上,这是因为初始化了全局路由。但回显服务器节点不知道第一个CSMA节点的MAC地址,因此它发了ARP。
2.003710 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50
2.007607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024 

7.3 third.cc

//1. 头文件
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/ssid.h"

//网络场景,包括了p2p、CSMA有线网络、WIFI无线网络的混合场景
// Default Network Topology
// n0: 无线网络的接入点AP。n5,n6,n7:连接到无线网络的终端STA。
//
//   Wifi 10.1.3.0
//                 AP
//  *    *    *    *
//  |    |    |    |    10.1.1.0
// n5   n6   n7   n0 -------------- n1   n2   n3   n4
//                   point-to-point  |    |    |    |
//                                   ================
//                                     LAN 10.1.2.0
// 2.命名空间
using namespace ns3;
// 3.定义记录组件
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
// 4.主函数
int 
main (int argc, char *argv[])
{
  bool verbose = true;
  uint32_t nCsma = 3;
  uint32_t nWifi = 3;
  bool tracing = false;

  CommandLine cmd;
  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
  cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
  cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
  cmd.AddValue ("tracing", "Enable pcap tracing", tracing);

  cmd.Parse (argc,argv);

  // The underlying restriction of 18 is due to the grid position
  // allocator's configuration; the grid layout will exceed the
  // bounding box if more than 18 nodes are provided.
  if (nWifi > 18)
    {
      std::cout << "nWifi should be 18 or less; otherwise grid layout exceeds the bounding box" << std::endl;
      return 1;
    }

  if (verbose)
    { //打印指定LOG组件信息
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }
    
  // 5.创建网络拓扑
  // 创建2个节点用于连接点对点链路
  NodeContainer p2pNodes;
  p2pNodes.Create (2);
  
  // 实例化PointToPointHelper,并设置相关默认属性
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
  
  // 在节点和信道间安装设备
  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);
  
  // 声明NodeContainer,放置CSMA网络的一部分节点,在点到点的节点容器中得到第一个节点,把它加入到CSMA设备的节点容器中。
  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);
  
  // 实例化CsmaHelper,并设置属性
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
  
  // 创建NetDeviceContainer与CSMA网络设备同步,安装到CSMA设备到选择节点上。
  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);
  
  // 建立节点,成为无线网络一部分
  NodeContainer wifiStaNodes;
  wifiStaNodes.Create (nWifi);
  NodeContainer wifiApNode = p2pNodes.Get (0);
  
  // 构建无线设备与无线节点之间的互连通道。
  // 首先要配置PHY和通道助手
  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();//默认传播延迟模型,默认损耗模型
  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();//默认误码率模型
  phy.SetChannel (channel.Create ());

  WifiHelper wifi;
  wifi.SetRemoteStationManager ("ns3::AarfWifiManager");// wifiRemoteStationManager主要用于wifi的速率控制(rate control)

  WifiMacHelper mac;
  Ssid = Ssid ("ns-3-ssid");
  mac.SetType ("ns3::StaWifiMac",//移动节点
               "Ssid", SsidValue (ssid),
               "ActiveProbing", BooleanValue (false));

  NetDeviceContainer staDevices;//安装移动节点
  staDevices = wifi.Install (phy, mac, wifiStaNodes);

  mac.SetType ("ns3::ApWifiMac",//AP节点
               "Ssid", SsidValue (ssid));

  NetDeviceContainer apDevices;//为AP节点安装应用
  apDevices = wifi.Install (phy, mac, wifiApNode);

  MobilityHelper mobility;//移动模型助手类

  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0),//起点坐标(0.0,0.0)
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (5.0),//x轴节点间距:5m
                                 "DeltaY", DoubleValue (10.0), //y轴节点间距:10m

                                 "GridWidth", UintegerValue (3),//每行最大节点数
                                 "LayoutType", StringValue ("RowFirst"));

  mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
                             "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
  mobility.Install (wifiStaNodes);//为AP节点设置移动模型

  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (wifiApNode);
//6.安装TCP/IP协议族
  InternetStackHelper stack;
  stack.Install (csmaNodes);
  stack.Install (wifiApNode);
  stack.Install (wifiStaNodes);

  Ipv4AddressHelper address;

  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer p2pInterfaces;
  p2pInterfaces = address.Assign (p2pDevices);

  address.SetBase ("10.1.2.0", "255.255.255.0");
  Ipv4InterfaceContainer csmaInterfaces;
  csmaInterfaces = address.Assign (csmaDevices);

  address.SetBase ("10.1.3.0", "255.255.255.0");
  address.Assign (staDevices);
  address.Assign (apDevices);
//7.安装应用程序
  UdpEchoServerHelper echoServer (9);

  ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (10.0));

  UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

  ApplicationContainer clientApps = 
    echoClient.Install (wifiStaNodes.Get (nWifi - 1));
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));
//8.设置路由
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  Simulator::Stop (Seconds (10.0));
//9.数据追踪
  if (tracing == true)
    {
      pointToPoint.EnablePcapAll ("third");
      phy.EnablePcap ("third", apDevices.Get (0));
      csma.EnablePcap ("third", csmaDevices.Get (0), true);
    }
//10.启动与结束
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}


7.4 forth.cc

7.5 fifth.cc

7.5.1 哪个变量作为Trace Source

7.5.2 怎么构造作为Trace Sink的回调函数

7.5.3 整体把握fifth.cc

7.5.4 运行fifth.cc

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值