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 实例程序
- 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
}
// 成员函数定义
- 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);
包括两层的协议组件:
- Layer-3 protocols
IPv4L3Protocol类 - 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中。
有多种应用程序:
- 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.");
}
- 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
- Radvd
- 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.");
}
- PacketSink模块:接收数据包
- OnOffApplication
- 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。
-
助手
-
属性
-
跟踪
-
验证
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;
}