ns3学习之路(二)

 


           node 0                 node 1
     +----------------+    +----------------+
     |    ns-3 TCP    |    |    ns-3 TCP    |
     +----------------+    +----------------+
     |    10.1.1.1    |    |    10.1.1.2    |
     +----------------+    +----------------+
     | point-to-point |    | point-to-point |
     +----------------+    +----------------+
             |                     |
             +---------------------+
                 5 Mbps, 2 ms

我们想要查看ns3 TCP的拥塞控制窗口的变化,我们需要加快一个流并且hook发送包的套接字的拥塞控制窗口的属性(Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,一旦hook某个事件之后,当该事件发生时,对该事件进行hook的程序就会收到系统的通知,这时程序就能在第一时间对该事件做出响应)。 通常会使用一个开关的应用程序去生成流,但是这样会导致问题 ,首先,这个开关应用程序的套接字编程直到应用程序启动才开始创建, 所以我们将不能hool配置时间内的socket;其次,即使我们在开始之后才安排一个包,因为socket并不公开所以我们并不能得到它。

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;
  Address         m_peer;
  uint32_t        m_packetSize;
  uint32_t        m_nPackets;
  DataRate        m_dataRate;
  EventId         m_sendEvent;
  bool            m_running;
  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;
}

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;
}

void
MyApp::StartApplication (void)
{
  m_running = true;
  m_packetsSent = 0;
  m_socket->Bind ();
  m_socket->Connect (m_peer);
  SendPacket ();
}

//析构函数:检查当前是否有发包行为,如果有,则取消发包;随后关闭套接字链接
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 ();
    }
}

void 
MyApp::ScheduleTx (void)
{
  //计算一个包传输的时间t,当时间t之后,发送一个包
  if (m_running)
    {
      Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));
      m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
    }
}

//当拥塞控制窗口大小发生变化的时候 日志打印旧的窗口
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 ());
}
  uint16_t sinkPort = 8080;
  Address sinkAddress (InetSocketAddress (interfaces.GetAddress (1), sinkPort));
  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
  ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
  sinkApps.Start (Seconds (0.));
  sinkApps.Stop (Seconds (20.));

将node1视为接收节点,为它绑定一个端口号8080,packetSink是一个对于on-off applocation的补充类,它可以接收和消耗到某一个地址和端口的流量。 

PacketSinkHelper::PacketSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort)) 第一个参数选定用于创建套接字的factory类型,绑定接收端的IP地址和端口

其中,Ipv4Address::GetAny ()返回主机的所有IP地址。

  1. GetAny()返回0.0.0.0 最特殊的一个ip地址,代表的是本机所有ip地址,不管你有多少个网口,多少个ip,如果监听本机的0.0.0.0上的端口,就等于监听机器上的所有ip端口。
  2. 127.0.0.1代表本地回环地址
  3. 主机的IP地址 是公网ip地址,这些是在网络中代表本机的ip地址,可通过此ip地址远程访问或控制主机

将PacketSinkApplication安装到 node 1

  Ptr<MyApp> app = CreateObject<MyApp> ();
  app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
  nodes.Get (0)->AddApplication (app);
  app->SetStartTime (Seconds (1.));
  app->SetStopTime (Seconds (20.));

将node 0视为发送端,将MyApp安装到node0上

  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndChange));

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

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值