NS-3 源碼修改--實現tcp數據包特徵(大小和間隔)服從特定分佈

NS-3源文件中包含有許多樣例和說明文檔,大家可以參考學習。針對本實驗室需要完成工作的一部分,也就是源節點向目的節點發送Tcp數據包,數據包大小滿足均勻分佈,發包過程滿足泊松分佈(即發包間隔滿足指數分佈)的要求,沒有現成的樣例可以借鑑,思考之後,決定修改onoffapplication和OnOffHelper相關源碼。

OnOffApplication類聲明和實現中,PacketSize是一個常數,

.AddAttribute ("PacketSize", "The size of packets sent in on state",
                 UintegerValue (512),
                 MakeUintegerAccessor (&OnOffApplication::m_pktSize),
                 MakeUintegerChecker<uint32_t> (1))

一旦設定,本次仿真無法更改;
而且也沒有發包間隔Interval這一屬性。
爲不影響系統其他模塊的使用,將涉及到onoffapplication類定義和聲明的頭文件,源文件全部拷貝進入一個.cc文件。包括onoff-application.h;onoff-application.cc;on-off helper.h;onoff helper.cc
相關類名之前加上前綴,如my,即類名分別爲myOnOffApplication,myOnOffHelper。
新增變量:

Ptr<RandomVariableStream>  m_interval;    
Ptr<RandomVariableStream>  m__packetsize;

myOnOffApplication類實現中,增加語句

.AddAttribute ("PacketSize", "The size of packets sent in on state",
                   StringValue ("ns3::ConstantRandomVariable[Constant=137]"),
                   MakePointerAccessor (&myOnOffApplication::m__packetsize),
                   MakePointerChecker <RandomVariableStream>())
.AddAttribute ("Interval", "The time between packets sent in on state",
                   StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
                   MakePointerAccessor (&myOnOffApplication::m_interval),
                   MakePointerChecker <RandomVariableStream>())

在成員函數myOnOffApplication::AssignStreams (int64_t stream)中添加語句

m_interval->SetStream (stream + 2);
m__packetsize->SetStream (stream + 3);
return 4;

在成員函數myOnOffApplication::ScheduleNextTx ()中添加語句

 m_pktSize=m__packetsize->GetValue();

來控制數據包大小;
添加語句

double myinterval=m_interval->GetValue();
cout << "the interval is "<<myinterval<<endl;
Time nextTime (Seconds (bits /
                          static_cast<double>(m_cbrRate.GetBitRate ())+myinterval)); 
NS_LOG_LOGIC ("nextTime = " << nextTime);

之後只需修改OnOffHelper類名爲myOnOffHelper即可。
關鍵是數據PacketSize和Interval格式的改變,將兩者都定義爲隨機變量流。

統計數據包大小和發包間隔,利用Gnuplot畫圖如下
這裏寫圖片描述
這裏寫圖片描述
數據包大小在100-137字節之間均勻分佈;
發包間隔爲指數分佈。

希望對大家的學習有所幫助!
可直接運行的源碼如下:

#include <fstream>
#include "ns3/gnuplot.h"
#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/random-variable-stream.h"
#include "ns3/rng-seed-manager.h"
#include <iostream>
#include "ns3/gnuplot.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/netanim-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-layout-module.h"
#include "ns3/netanim-module.h"
#include "ns3/address.h"
#include "ns3/application.h"
#include "ns3/event-id.h"
#include "ns3/ptr.h"
#include "ns3/data-rate.h"
#include "ns3/traced-callback.h"
#include "ns3/log.h"
#include "ns3/address.h"
#include "ns3/inet-socket-address.h"
#include "ns3/inet6-socket-address.h"
#include "ns3/packet-socket-address.h"
#include "ns3/node.h"
#include "ns3/nstime.h"
#include "ns3/data-rate.h"
#include "ns3/random-variable-stream.h"
#include "ns3/socket.h"
#include "ns3/simulator.h"
#include "ns3/socket-factory.h"
#include "ns3/packet.h"
#include "ns3/uinteger.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/onoff-application.h"
#include "ns3/udp-socket-factory.h"
#include "ns3/string.h"
#include "ns3/pointer.h"
#include "ns3/on-off-helper.h"
#include "ns3/inet-socket-address.h"
#include "ns3/packet-socket-address.h"
#include "ns3/string.h"
#include "ns3/data-rate.h"
#include "ns3/uinteger.h"
#include "ns3/names.h"
#include "ns3/random-variable-stream.h"
#include <stdint.h>
#include <string>
#include "ns3/object-factory.h"
#include "ns3/address.h"
#include "ns3/attribute.h"
#include "ns3/net-device.h"
#include "ns3/node-container.h"
#include "ns3/application-container.h"
#include "ns3/onoff-application.h"
#include <fstream>
#include "ns3/gnuplot.h"
#include "algorithm"
using namespace std;
using namespace ns3;
///////////////////////統計畫圖模塊/////////
// Gnuplot2dDataset dataset_interval2;
std::string fileNameWithNoExtension = "uniform";
std::string graphicsFileName        = fileNameWithNoExtension + ".png";
std::string plotFileName            = fileNameWithNoExtension + ".plt";
std::string plotTitle               = "packetsizes interval";
std::string dataTitle               = "uniform-D Data";
// Instantiate the plot and set its title.
Gnuplot plot (graphicsFileName);
Gnuplot2dDataset dataset_interval;
/////////////////////////////////

std::string fileNameWithNoExtension2 = "packetsize";
std::string graphicsFileName2        = fileNameWithNoExtension2 + ".png";
std::string plotFileName2            = fileNameWithNoExtension2 + ".plt";
std::string plotTitle2               = "packetsizes ";
  std::string dataTitle2               = "uniform-D Data";

  // Instantiate the plot and set its title.
  Gnuplot plot2 (graphicsFileName2);
  Gnuplot2dDataset dataset_packetsize;
//dataset_interval.SetTitle (dataTitle);
  //dataset_interval.SetStyle (Gnuplot2dDataset::LINES_POINTS);
  int count_packets=0;
  double data_interval[48];
  int    data_packetsize[48];
////////////////////////////////////////////////////////////////////////





// onoff-application .h  類聲明
namespace ns3 {

class Address;
class RandomVariableStream;
class Socket;

class myOnOffApplication : public Application
{
public:
  /**
   * \brief Get the type ID.
   * \return the object TypeId
   */
  static TypeId GetTypeId (void);

  myOnOffApplication ();

  virtual ~myOnOffApplication();

  /**
   * \brief Set the total number of bytes to send.
   *
   * Once these bytes are sent, no packet is sent again, even in on state.
   * The value zero means that there is no limit.
   *
   * \param maxBytes the total number of bytes to send
   */
  void SetMaxBytes (uint32_t maxBytes);

  /**
   * \brief Return a pointer to associated socket.
   * \return pointer to associated socket
   */
  Ptr<Socket> GetSocket (void) const;

 /**
  * \brief Assign a fixed random variable stream number to the random variables
  * used by this model.
  *
  * \param stream first stream index to use
  * \return the number of stream indices assigned by this model
  */
  int64_t AssignStreams (int64_t stream);

protected:
  virtual void DoDispose (void);
private:
  // inherited from Application base class.
  virtual void StartApplication (void);    // Called at time specified by Start
  virtual void StopApplication (void);     // Called at time specified by Stop

  //helpers
  /**
   * \brief Cancel all pending events.
   */
  void CancelEvents ();
   void StartSending ();
  /**
   * \brief Start an Off period
   */
  void StopSending ();

  void SendPacket ();

  Ptr<Socket>     m_socket;       //!< Associated socket
  Address         m_peer;         //!< Peer address
  bool            m_connected;    //!< True if connected
  Ptr<RandomVariableStream>  m_onTime;       //!< rng for On Time
  Ptr<RandomVariableStream>  m_offTime;      //!< rng for Off Time
  Ptr<RandomVariableStream>  m_interval;    
  Ptr<RandomVariableStream>  m__packetsize;
  DataRate        m_cbrRate;      //!< Rate that data is generated
  DataRate        m_cbrRateFailSafe;      //!< Rate that data is generated (check copy)
  uint32_t        m_pktSize;      //!< Size of packets
  uint32_t        m_residualBits; //!< Number of generated, but not sent, bits
  Time            m_lastStartTime; //!< Time last packet sent
  uint32_t        m_maxBytes;     //!< Limit total number of bytes sent
  uint32_t        m_totBytes;     //!< Total bytes sent so far
  EventId         m_startStopEvent;     //!< Event id for next start or stop event
  EventId         m_sendEvent;    //!< Event id of pending "send packet" event
  TypeId          m_tid;          //!< Type of the socket used
 // int             count_packets;
  /// Traced Callback: transmitted packets.
  TracedCallback<Ptr<const Packet> > m_txTrace;

private:
  /**
   * \brief Schedule the next packet transmission
   */
  void ScheduleNextTx ();
  /**
   * \brief Schedule the next On period start
   */
  void ScheduleStartEvent ();
  /**
   * \brief Schedule the next Off period start
   */
  void ScheduleStopEvent ();
  void ConnectionSucceeded (Ptr<Socket> socket);
  /**
   * \brief Handle a Connection Failed event
   * \param socket the not connected socket
   */
  void ConnectionFailed (Ptr<Socket> socket);
};

} // namespace ns3







///////////////////////


///////////////////////onoff-application.cc  類的實現 
namespace ns3 {

NS_LOG_COMPONENT_DEFINE ("myOnOffApplication");

NS_OBJECT_ENSURE_REGISTERED (myOnOffApplication);

TypeId
myOnOffApplication::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::myOnOffApplication")
    .SetParent<Application> ()
    .SetGroupName("Applications")
    .AddConstructor<myOnOffApplication> ()
    .AddAttribute ("DataRate", "The data rate in on state.",
                   DataRateValue (DataRate ("500kb/s")),
                   MakeDataRateAccessor (&myOnOffApplication::m_cbrRate),
                   MakeDataRateChecker ())
    .AddAttribute ("PacketSize", "The size of packets sent in on state",
                   StringValue ("ns3::ConstantRandomVariable[Constant=137]"),
                   MakePointerAccessor (&myOnOffApplication::m__packetsize),
                   MakePointerChecker <RandomVariableStream>())

    .AddAttribute ("Interval", "The time between packets sent in on state",
                   StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
                   MakePointerAccessor (&myOnOffApplication::m_interval),
                   MakePointerChecker <RandomVariableStream>())


    .AddAttribute ("Remote", "The address of the destination",
                   AddressValue (),
                   MakeAddressAccessor (&myOnOffApplication::m_peer),
                   MakeAddressChecker ())
    .AddAttribute ("OnTime", "A RandomVariableStream used to pick the duration of the 'On' state.",
                   StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
                   MakePointerAccessor (&myOnOffApplication::m_onTime),
                   MakePointerChecker <RandomVariableStream>())
    .AddAttribute ("OffTime", "A RandomVariableStream used to pick the duration of the 'Off' state.",
                   StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
                   MakePointerAccessor (&myOnOffApplication::m_offTime),
                   MakePointerChecker <RandomVariableStream>())
    .AddAttribute ("MaxBytes",
                   "The total number of bytes to send. Once these bytes are sent, "
                   "no packet is sent again, even in on state. The value zero means "
                   "that there is no limit.",
                   UintegerValue (0),
                   MakeUintegerAccessor (&myOnOffApplication::m_maxBytes),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("Protocol", "The type of protocol to use.",
                   TypeIdValue (UdpSocketFactory::GetTypeId ()),
                   MakeTypeIdAccessor (&myOnOffApplication::m_tid),
                   MakeTypeIdChecker ())
    .AddTraceSource ("Tx", "A new packet is created and is sent",
                     MakeTraceSourceAccessor (&myOnOffApplication::m_txTrace),
                     "ns3::Packet::TracedCallback")
  ;
  return tid;
}
myOnOffApplication::myOnOffApplication ()
  : m_socket (0),
    m_connected (false),
    m_residualBits (0),
    m_lastStartTime (Seconds (0)),
   // count_packets(0),
    m_totBytes (0)
{
  NS_LOG_FUNCTION (this);
}

myOnOffApplication::~myOnOffApplication()
{
  NS_LOG_FUNCTION (this);
}

void
myOnOffApplication::SetMaxBytes (uint32_t maxBytes)
{
  NS_LOG_FUNCTION (this << maxBytes);
  m_maxBytes = maxBytes;
}

Ptr<Socket>
myOnOffApplication::GetSocket (void) const
{
  NS_LOG_FUNCTION (this);
  return m_socket;
}

int64_t
myOnOffApplication::AssignStreams (int64_t stream)
{
  NS_LOG_FUNCTION (this << stream);
  m_onTime->SetStream (stream);
  m_offTime->SetStream (stream + 1);
  m_interval->SetStream (stream + 2);
  m__packetsize->SetStream (stream + 3);
  return 4;
}

void
myOnOffApplication::DoDispose (void)
{
  NS_LOG_FUNCTION (this);

  m_socket = 0;
  // chain up
  Application::DoDispose ();
}

// Application Methods
void myOnOffApplication::StartApplication () // Called at time specified by Start
{
  NS_LOG_FUNCTION (this);

  // Create the socket if not already
  if (!m_socket)
    {
      m_socket = Socket::CreateSocket (GetNode (), m_tid);
      if (Inet6SocketAddress::IsMatchingType (m_peer))
        {
          m_socket->Bind6 ();
        }
      else if (InetSocketAddress::IsMatchingType (m_peer) ||
               PacketSocketAddress::IsMatchingType (m_peer))
        {
          m_socket->Bind ();
        }
      m_socket->Connect (m_peer);
      m_socket->SetAllowBroadcast (true);
      m_socket->ShutdownRecv ();

      m_socket->SetConnectCallback (
        MakeCallback (&myOnOffApplication::ConnectionSucceeded, this),
        MakeCallback (&myOnOffApplication::ConnectionFailed, this));
    }
  m_cbrRateFailSafe = m_cbrRate;

  // Insure no pending event
  CancelEvents ();
  // If we are not yet connected, there is nothing to do here
  // The ConnectionComplete upcall will start timers at that time
  //if (!m_connected) return;
  ScheduleStartEvent ();
}

void myOnOffApplication::StopApplication () // Called at time specified by Stop
{
  NS_LOG_FUNCTION (this);

  CancelEvents ();
  if(m_socket != 0)
    {
      m_socket->Close ();
    }
  else
    {
      NS_LOG_WARN ("myOnOffApplication found null socket to close in StopApplication");
    }
}
void myOnOffApplication::CancelEvents ()
{
  NS_LOG_FUNCTION (this);

  if (m_sendEvent.IsRunning () && m_cbrRateFailSafe == m_cbrRate )
    { // Cancel the pending send packet event
      // Calculate residual bits since last packet sent
      Time delta (Simulator::Now () - m_lastStartTime);
      int64x64_t bits = delta.To (Time::S) * m_cbrRate.GetBitRate ();
      m_residualBits += bits.GetHigh ();
    }
  m_cbrRateFailSafe = m_cbrRate;
  Simulator::Cancel (m_sendEvent);
  Simulator::Cancel (m_startStopEvent);
}

// Event handlers
void myOnOffApplication::StartSending ()
{
  NS_LOG_FUNCTION (this);
  m_lastStartTime = Simulator::Now ();
  ScheduleNextTx ();  // Schedule the send packet event
  ScheduleStopEvent ();
}

void myOnOffApplication::StopSending ()
{
  NS_LOG_FUNCTION (this);
  CancelEvents ();

  ScheduleStartEvent ();
}
void myOnOffApplication::ScheduleNextTx ()
{
  NS_LOG_FUNCTION (this);

  if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
    {
      cout<<"第幾次進入 ScheduleNextTx ()"<<endl;  
      m_pktSize=m__packetsize->GetValue();   // 添加這一個數據包大小控制語句

      data_packetsize[count_packets]=m_pktSize;

      uint32_t bits = m_pktSize * 8 - m_residualBits;
      NS_LOG_LOGIC ("bits = " << bits);

      double myinterval=m_interval->GetValue();
      cout << "the interval is "<<myinterval<<endl;     
      data_interval[count_packets]=myinterval;
      count_packets++;

     // dataset_interval.Add(count_packets,myinterval);

      Time nextTime (Seconds (bits /
                              static_cast<double>(m_cbrRate.GetBitRate ())+myinterval)); // Time till next packet
      NS_LOG_LOGIC ("nextTime = " << nextTime);
      m_sendEvent = Simulator::Schedule (nextTime,
                                         &myOnOffApplication::SendPacket, this);
    }
  else
    { // All done, cancel any pending events
      StopApplication ();
    }
}

void myOnOffApplication::ScheduleStartEvent ()
{  // Schedules the event to start sending data (switch to the "On" state)
  NS_LOG_FUNCTION (this);

  Time offInterval = Seconds (m_offTime->GetValue ());
  NS_LOG_LOGIC ("start at " << offInterval);
  m_startStopEvent = Simulator::Schedule (offInterval, &myOnOffApplication::StartSending, this);
}

void myOnOffApplication::ScheduleStopEvent ()
{  // Schedules the event to stop sending data (switch to "Off" state)
  NS_LOG_FUNCTION (this);

  Time onInterval = Seconds (m_onTime->GetValue ());
  NS_LOG_LOGIC ("stop at " << onInterval);
  m_startStopEvent = Simulator::Schedule (onInterval, &myOnOffApplication::StopSending, this);
}
void myOnOffApplication::SendPacket ()
{
  NS_LOG_FUNCTION (this);

  NS_ASSERT (m_sendEvent.IsExpired ());
  Ptr<Packet> packet = Create<Packet> (m_pktSize);
  m_txTrace (packet);
  m_socket->Send (packet);
  m_totBytes += m_pktSize;
  if (InetSocketAddress::IsMatchingType (m_peer))
    {
      NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
                   << "s on-off application sent "
                   <<  packet->GetSize () << " bytes to "
                   << InetSocketAddress::ConvertFrom(m_peer).GetIpv4 ()
                   << " port " << InetSocketAddress::ConvertFrom (m_peer).GetPort ()
                   << " total Tx " << m_totBytes << " bytes");
    }
  else if (Inet6SocketAddress::IsMatchingType (m_peer))
    {
      NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
                   << "s on-off application sent "
                   <<  packet->GetSize () << " bytes to "
                   << Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6 ()
                   << " port " << Inet6SocketAddress::ConvertFrom (m_peer).GetPort ()
                   << " total Tx " << m_totBytes << " bytes");
    }
  m_lastStartTime = Simulator::Now ();
  m_residualBits = 0;
  ScheduleNextTx ();
}


void myOnOffApplication::ConnectionSucceeded (Ptr<Socket> socket)
{
  NS_LOG_FUNCTION (this << socket);
  m_connected = true;
}

void myOnOffApplication::ConnectionFailed (Ptr<Socket> socket)
{
  NS_LOG_FUNCTION (this << socket);
}


} // Namespace ns3







//////////////////////// on-off helper .h   頭文件

namespace ns3 {

class DataRate;

/**
 * \ingroup onoff
 * \brief A helper to make it easier to instantiate an ns3::myOnOffApplication 
 * on a set of nodes.
 */
class myOnOffHelper
{
public:
  /**
   * Create an myOnOffHelper to make it easier to work with myOnOffApplications
   *
   * \param protocol the name of the protocol to use to send traffic
   *        by the applications. This string identifies the socket
   *        factory type used to create sockets for the applications.
   *        A typical value would be ns3::UdpSocketFactory.
   * \param address the address of the remote node to send traffic
   *        to.
   */
  myOnOffHelper (std::string protocol, Address address);

  /**
   * Helper function used to set the underlying application attributes.
   *
   * \param name the name of the application attribute to set
   * \param value the value of the application attribute to set
   */
  void SetAttribute (std::string name, const AttributeValue &value);

  /**
   * Helper function to set a constant rate source.  Equivalent to
   * setting the attributes OnTime to constant 1000 seconds, OffTime to 
   * constant 0 seconds, and the DataRate and PacketSize set accordingly
   *
   * \param dataRate DataRate object for the sending rate
   * \param packetSize size in bytes of the packet payloads generated
   */
  void SetConstantRate (DataRate dataRate, uint32_t packetSize = 512);

  /**
   * Install an ns3::myOnOffApplication on each node of the input container
   * configured with all the attributes set with SetAttribute.
   *
   * \param c NodeContainer of the set of nodes on which an myOnOffApplication 
   * will be installed.
   * \returns Container of Ptr to the applications installed.
   */
  ApplicationContainer Install (NodeContainer c) const;

  ApplicationContainer Install (Ptr<Node> node) const;

  /**
   * Install an ns3::myOnOffApplication on the node configured with all the 
   * attributes set with SetAttribute.
   *
   * \param nodeName The node on which an myOnOffApplication will be installed.
   * \returns Container of Ptr to the applications installed.
   */
  ApplicationContainer Install (std::string nodeName) 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.  The Install() method should have previously been
  * called by the user.
  *
  * \param stream first stream index to use
  * \param c NodeContainer of the set of nodes for which the myOnOffApplication
  *          should be modified to use a fixed stream
  * \return the number of stream indices assigned by this helper
  */
  int64_t AssignStreams (NodeContainer c, int64_t stream);

private:
  /**
   * Install an ns3::myOnOffApplication on the node configured with all the 
   * attributes set with SetAttribute.
   *
   * \param node The node on which an myOnOffApplication will be installed.
   * \returns Ptr to the application installed.
   */
  Ptr<Application> InstallPriv (Ptr<Node> node) const;

  ObjectFactory m_factory; //!< Object factory.
};

} // namespace ns3








////////////////////////



//////////  onoff helper.cc   實現    
namespace ns3 {

myOnOffHelper::myOnOffHelper (std::string protocol, Address address)
{
  m_factory.SetTypeId ("ns3::myOnOffApplication");
  m_factory.Set ("Protocol", StringValue (protocol));
  m_factory.Set ("Remote", AddressValue (address));
}

void
myOnOffHelper::SetAttribute (std::string name, const AttributeValue &value)
{
  m_factory.Set (name, value);
}

ApplicationContainer
myOnOffHelper::Install (Ptr<Node> node) const
{
  return ApplicationContainer (InstallPriv (node));
}

ApplicationContainer
myOnOffHelper::Install (std::string nodeName) const
{
  Ptr<Node> node = Names::Find<Node> (nodeName);
  return ApplicationContainer (InstallPriv (node));
}

ApplicationContainer
myOnOffHelper::Install (NodeContainer c) const
{
  ApplicationContainer apps;
  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
    {
      apps.Add (InstallPriv (*i));
    }

  return apps;
}

Ptr<Application>
myOnOffHelper::InstallPriv (Ptr<Node> node) const
{
  Ptr<Application> app = m_factory.Create<Application> ();
  node->AddApplication (app);

  return app;
}
int64_t
myOnOffHelper::AssignStreams (NodeContainer c, int64_t stream)
{
  int64_t currentStream = stream;
  Ptr<Node> node;
  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
    {
      node = (*i);
      for (uint32_t j = 0; j < node->GetNApplications (); j++)
        {
          Ptr<myOnOffApplication> onoff = DynamicCast<myOnOffApplication> (node->GetApplication (j));
          if (onoff)
            {
              currentStream += onoff->AssignStreams (currentStream);
            }
        }
    }
  return (currentStream - stream);
}

void
myOnOffHelper::SetConstantRate (DataRate dataRate, uint32_t packetSize)
{
  m_factory.Set ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1000]"));
  m_factory.Set ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
  m_factory.Set ("DataRate", DataRateValue (dataRate));
 // m_factory.Set ("PacketSize", UintegerValue (packetSize));

  m_factory.Set ("PacketSize",StringValue ("ns3::ConstantRandomVariable[Constant=532]"));
  m_factory.Set ("Interval", StringValue ("ns3::ConstantRandomVariable[Constant=0.1]"));


}

} // namespace ns3







//////////
// Network topology

//     n0--- -----n1



using namespace ns3;


//NS_LOG_COMPONENT_DEFINE ("tcp-one-point2one-point");

int

main (int argc, char *argv[])

{

/*   
///////////////////////統計畫圖模塊/////////

  std::string fileNameWithNoExtension = "uniform";
  std::string graphicsFileName        = fileNameWithNoExtension + ".png";
  std::string plotFileName            = fileNameWithNoExtension + ".plt";
  std::string plotTitle               = "2-D Plot";
  std::string dataTitle               = "uniform-D Data";

  // Instantiate the plot and set its title.
  Gnuplot plot (graphicsFileName);
  plot.SetTitle (plotTitle);

  // Make the graphics file, which the plot file will create when it
  // is used with Gnuplot, be a PNG file.
  plot.SetTerminal ("png");

  // Set the labels for each axis.
  plot.SetLegend ("X Values", "Y Values");

  // Set the range for the x axis.
  plot.AppendExtra ("set xrange [1:+50]");

  // Instantiate the dataset, set its title, and make the points be
  // plotted along with connecting lines.
  Gnuplot2dDataset dataset_interval;
  dataset_interval.SetTitle (dataTitle);
  dataset_interval.SetStyle (Gnuplot2dDataset::LINES_POINTS);

//////////////////////////////////////////////////////////////////////// 
 */ 



  //

  // Set up some default values for the simulation.

  //
    LogComponentEnable("myOnOffApplication",LOG_LEVEL_INFO);

  // Config::SetDefault ("ns3::myOnOffApplication::PacketSize", UintegerValue (700));


  // ??? try and stick 15kb/s into the data rate

  Config::SetDefault ("ns3::myOnOffApplication::DataRate", StringValue ("50Mb/s"));



  CommandLine cmd;
  cmd.Parse (argc, argv);

  NodeContainer nodes;
  nodes.Create (2);  

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

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


  //NS_LOG_INFO ("Install internet stack on all nodes.");
  InternetStackHelper stack;
  stack.Install (nodes);

 // NS_LOG_INFO ("Assign IP Addresses.");
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");

  Ipv4InterfaceContainer interfaces = address.Assign (devices);


  //NS_LOG_INFO ("Create applications.");
  //
  // Create a packet sink on the star "hub" to receive packets.
  // 
  uint16_t port = 50000;

  Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
  ApplicationContainer hubApp = packetSinkHelper.Install (nodes.Get (1));       //接收端 n1 節點
  hubApp.Start (Seconds (0.0));
  hubApp.Stop (Seconds (200.0));


  //
  // Create OnOff applications to send TCP to the hub, one on each spoke node.  //

  myOnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
  onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=200]"));
  onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
  onOffHelper.SetAttribute ("MaxBytes",UintegerValue(0) );



 // onOffHelper.SetAttribute ("PacketSize", StringValue ("ns3::ConstantRandomVariable[Constant=137]"));

   onOffHelper.SetAttribute ("PacketSize", StringValue ("ns3::UniformRandomVariable[Min=100|Max=137]"));

  // onOffHelper.SetAttribute ("Interval", StringValue ("ns3::ConstantRandomVariable[Constant=2]"));

  //onOffHelper.SetAttribute ("Interval", StringValue ("ns3::UniformRandomVariable[Min=1|Max=4]"));

  onOffHelper.SetAttribute ("Interval", StringValue ("ns3::ExponentialRandomVariable[Mean=3.14|Bound=0.0]"));

  ApplicationContainer spokeApps;

  AddressValue remoteAddress (InetSocketAddress (interfaces.GetAddress(1), port));       //遠端地址  也就是接收端的IP地址
  onOffHelper.SetAttribute ("Remote", remoteAddress);
  spokeApps.Add(onOffHelper.Install(nodes.Get(0)));
  spokeApps.Start (Seconds (0.0));
  spokeApps.Stop (Seconds (200.0));






  //NS_LOG_INFO ("Enable static global routing.");
  //
  // Turn on global static routing so we can actually be routed across the star.
  //
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  //NS_LOG_INFO ("Enable pcap tracing.");
  //
  // Do pcap tracing on all point-to-point devices on all nodes.
  //
  pointToPoint.EnablePcapAll ("one-point2one-point");

 // NS_LOG_INFO ("Run Simulation.");
 // AnimationInterface anim ("one-point2one-point.xml");
  //double x1=12;
  //double y1=12;
  //double x2=24;
  //double y2=24;
  AnimationInterface::SetConstantPosition (nodes.Get(0),12,12);
  AnimationInterface::SetConstantPosition (nodes.Get(1),24,24);
  AnimationInterface anim ("one-point2one-point.xml");
  anim.EnablePacketMetadata();


 ////////////畫圖 
// Add the dataset to the plot.
  plot.SetTitle (plotTitle);

  // Make the graphics file, which the plot file will create when it
  // is used with Gnuplot, be a PNG file.
  plot.SetTerminal ("png");

  // Set the labels for each axis.
  plot.SetLegend ("X Values", "Y Values");

  // Set the range for the x axis.
  plot.AppendExtra ("set xrange [1:+50]");

 /*
  plot.AddDataset (dataset_interval);

  // Open the plot file.
  std::ofstream plotFile (plotFileName.c_str());

  // Write the plot file.
  plot.GenerateOutput (plotFile);

  // Close the plot file.
  plotFile.close();
 */

////////////////
  Simulator::Run ();
  sort(data_interval,data_interval+48);
  for (int i=0;i<48;i++)
 {

   dataset_interval.Add(i,data_interval[i]);
   dataset_packetsize.Add(i,data_packetsize[i]);
 }

 //  dataset_interval.Add(count_packets,myinterval);
  plot.AddDataset (dataset_interval);

  // Open the plot file.
  std::ofstream plotFile (plotFileName.c_str());

  // Write the plot file.
  plot.GenerateOutput (plotFile);

  // Close the plot file.
  plotFile.close();

  //////////////////////

  plot2.SetTitle (plotTitle2);

  // Make the graphics file, which the plot file will create when it
  // is used with Gnuplot, be a PNG file.
  plot2.SetTerminal ("png");

  // Set the labels for each axis.
  plot2.SetLegend ("X Values", "Y Values");

  // Set the range for the x axis.
  plot2.AppendExtra ("set xrange [-5:+60]");
  plot2.AppendExtra ("set yrange [60:+200]");


  plot2.AddDataset (dataset_packetsize);
  std::ofstream plotFile2 (plotFileName2.c_str());

  // Write the plot file.
  plot2.GenerateOutput (plotFile2);

  // Close the plot file.
  plotFile2.close();



  Simulator::Destroy ();
 // NS_LOG_INFO ("Done.");

  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章