NS3 fifth.cc注释

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

NS3 fifth.cc注释
最近在学NS3,tutorial的1-4代码注释都有很多帖子,但是5、6缺很少。所以贴一下查找后的代码及注释

主要参考官方tutorial的第8章。
本人缺乏相关的理论和代码基础,所有不太准确,望理解。

TCP与socket连接,可参考https://blog.csdn.net/u014618114/article/details/103242376
官方tutorial的第8章(8.3)
https://www.nsnam.org/docs/tutorial/html/tracing.html#real-example
NS3 利用Gnuplot生成拥塞窗口例子fifth.cc的png图像 可参考
https://www.cnblogs.com/zywnnblog/p/13469593.html

fifth.cc

代码如下:

/* 拥塞窗口实例
 * 配置期间绑定模拟时间建立动态实体内的trace源
 * fifth.cc在配置时建立了动态对象socket加入到APP中,挂起,运行时app开始调用socket把对象给系统
 * 重点学习: 
 *    1.application重载
 *    2.动态trace source如何绑定
 *    3.TCP协议安装
*/
//1.头文件
#include <fstream>
#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"

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

//3.日志组件
NS_LOG_COMPONENT_DEFINE ("FifthScriptExample");

//因此,首先,我们创建一个套接字并对其进行跟踪连接;然后我们将此套接字传递给我们的简单应用程序的构造函数,然后我们将其安装在源节点中。
class MyApp : public Application 
{
public:
  MyApp ();         //构造函数
  virtual ~MyApp(); //析构函数
  void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate);
private:
  virtual void StartApplication (void);
  virtual void StopApplication (void);
  void ScheduleTx (void);
  void SendPacket (void);

  Ptr<Socket>     m_socket;      //发送的socket
  Address         m_peer;        //对端的Address,注意与IPV4Address不一样
  uint32_t        m_packetSize;  //包长
  uint32_t        m_nPackets;    //发包数量
  DataRate        m_dataRate;    //数据速率
  EventId         m_sendEvent;   //发送事件
  bool            m_running;     //是否运行,true开始运行
  uint32_t        m_packetsSent; //已发送多少包
};

MyApp::MyApp ()
  : m_socket (0), 
    m_peer (), 
    m_packetSize (0), 
    m_nPackets (0), 
    m_dataRate (0), 
    m_sendEvent (), 
    m_running (false), 
    m_packetsSent (0)
{
}

MyApp::~MyApp()
{
  m_socket = 0;
}

//初始化成员变量 
//从跟踪角度来看,最重要是Ptr<Socket>套接字,我们需要在配置时提供给应用程序
//将Socket创建为一个TcpSocket,并把它传递给Set UP方法之前挂钩"CongestionWindow"跟踪源
void
MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate)
{
  m_socket = socket;
  m_peer = address;
  m_packetSize = packetSize;
  m_nPackets = nPackets;
  m_dataRate = dataRate;
}

//override 由模拟器自动调用 执行Socket Bind操作
void
MyApp::StartApplication (void)
{
  m_running = true;
  m_packetsSent = 0;
  m_socket->Bind ();
  m_socket->Connect (m_peer); //执行与地址为m_peer的TCP建立连接所需的操作 连接后,应用程序调用SendPacket开始创建模拟事件
  SendPacket ();
}

//在仿真前,会创建事件。如果事件正在执行/等待执行,IsRunning将返回true.
//这里,如果IsRunning返回true,我们取消事件,并从模拟器事件队列中删除。
//打破应用程序继续发送数据包的事件链,应用程序进入安静。之后,关闭socket,关闭TCP连接
//当m_socket=0,Socket已经在析构函数中删除了。这将移除底层Ptr<Socket>的最后一个索引。
void 
MyApp::StopApplication (void)
{
  m_running = false;

  if (m_sendEvent.IsRunning ())
    {
      Simulator::Cancel (m_sendEvent);
    }

  if (m_socket)
    {
      m_socket->Close ();
    }
}

//创建数据包,发送
void 
MyApp::SendPacket (void)
{
  Ptr<Packet> packet = Create<Packet> (m_packetSize);
  m_socket->Send (packet);

  if (++m_packetsSent < m_nPackets)  //已发送的数据包<给定的发布发包数量,就ScheduleTx ();
    {
      ScheduleTx ();
    }
}

//如果应用程序正在运行,安排新事件,再次调用SendPacket
void 
MyApp::ScheduleTx (void)
{
  if (m_running)
    { 
      Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ()))); //应用层数据速率-应用层产生bit的速率
      m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
    }
}

//实现相应的跟踪接收器 只记录当前模拟时间和拥塞窗口改变的新值。可将输出加载到图形界面gunplot/excel
static void
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
  NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
}

//追踪接收器 显示数据包被丢弃 当网络设备的网络层丢包时,触发
static void
RxDrop (Ptr<const Packet> p)  
{
  NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
}

//4.主函数
int 
main (int argc, char *argv[])
{ 
  //读取命令行参数
  CommandLine cmd (__FILE__);
  cmd.Parse (argc, argv);
  
  //5.创建网络拓扑
  NodeContainer nodes;  //创建2节点
  nodes.Create (2);

  PointToPointHelper pointToPoint;  //设置P2P信道属性
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  NetDeviceContainer devices;     //连接信道与节点
  devices = pointToPoint.Install (nodes);

  //引入ErrorModel模型:RateErrorModel
  Ptr<RateErrorModel> em = CreateObject<RateErrorModel> ();
  em->SetAttribute ("ErrorRate", DoubleValue (0.00001));
  devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
  //上面的代码实例化了一个 RateErrorModel 对象,我们将“ErrorRate”属性设置为所需的值。然后,我们将生成的实例化 RateErrorModel 设置为点对点 NetDevice 使用的错误模型

  //6.安装TCP/IP协议栈
  InternetStackHelper stack;
  stack.Install (nodes);

  Ipv4AddressHelper address;  //分配IP
  address.SetBase ("10.1.1.0", "255.255.255.252");
  Ipv4InterfaceContainer interfaces = address.Assign (devices);

  //设置socket端口
  uint16_t sinkPort = 8080;
  Address sinkAddress (InetSocketAddress (interfaces.GetAddress (1), sinkPort)); 
  //实例了PacketSinkHelper,告诉ns3::TcpSocketFactory创建socket
  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
  ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1)); //绑定的地址和端口
  sinkApps.Start (Seconds (0.));
  sinkApps.Stop (Seconds (20.));

  //创建socket并连接跟踪源
  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ()); //
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndChange));

  //7.安装应用程序 
  //实例化应用程序 手动创建安装
  Ptr<MyApp> app = CreateObject<MyApp> (); //创建MyApp
  app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps")); //使用什么socket,地址,数据量,事件数,数据速率
  nodes.Get (0)->AddApplication (app);//应用程序添加到节点中
  app->SetStartTime (Seconds (1.));   //开始结束时间
  app->SetStopTime (Seconds (20.));  

  devices.Get (1)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&RxDrop)); //回调

  Simulator::Stop (Seconds (20));
  Simulator::Run ();
  Simulator::Destroy ();

  return 0;
}

以上即fifth.cc

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值