天天看點

【網絡仿真】ns-3基礎(下)6 ns-3其他子產品7 示例

6 ns-3其他子產品

6.1 網絡子產品

分組:傳遞的消息,模拟器基本對象。ns-3中每個分組包括一個位元組緩沖區和一個Tag清單,通過Header類和Trailer類對緩沖區資料進行添加和删除。

6.1.1 分組

【網絡仿真】ns-3基礎(下)6 ns-3其他子產品7 示例

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 <[email protected]>
 */

#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個跟蹤檔案:

【網絡仿真】ns-3基礎(下)6 ns-3其他子產品7 示例
【網絡仿真】ns-3基礎(下)6 ns-3其他子產品7 示例

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