转自:http://blog.sina.com.cn/s/blog_7ec2ab360102wxh3.html
这节我们将利用一个无线网络来进一步扩展关于NS3网络设备和信道的知识。其中,我们将看到WifiHelper,其作用类似于PointToPointHelper和CsmaHelper。
在example/tutorial下的third.cc脚本是second.cc的升级版,我们在third.cc中添加了Wifi网络。
一.third.cc代码
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/wifi-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
// Default Network Topology
// 网络拓扑结构
// Number of wifi or csma nodes can be increased up to 250
// |
// Rank 0 | Rank 1
// ----------------------------|----------------------------
// 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
//在p2p网络左边,我们添加了10.1.3.0的WiFi网络。其中n0为AP节点,n5、6、7为STA节点。与nCsma相似,我们可以通过设置nWifi来控制在仿真中出现的STA节点数。在仿真中一定存在一个AP节点!
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
int
main (int argc, char *argv[])
{
bool verbose = true;
uint32_t nCsma = 3;
uint32_t nWifi = 3; // 在WiFi网络中,除了一个AP节点以外的STA节点数
bool tracing = false; // 在trace时,是否启用promiscuous模式,初始化为不启用
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);
// 查看csma和wifi节点的是有效数量,各不能超过250
// Check for valid number of csma or wifi nodes
// 250 should be enough, otherwise IP addresses
// soon become an issue
if (nWifi > 250 || nCsma > 250)
{
std::cout << "Too many wifi or csma nodes, no more than 250 each." << std::endl;
return 1;
}
if (verbose) // UDP日志启用判断
{
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
NodeContainer p2pNodes; // 创建p2p节点,并且对设备、信道进行设置安装
p2pNodes.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
NodeContainer csmaNodes; // 创建csma节点对象
csmaNodes.Add (p2pNodes.Get (1)); // p2p网络中,索引为1的节点将同时作为csma节点
csmaNodes.Create (nCsma);
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
NodeContainer wifiStaNodes; // 创建STA节点对象
wifiStaNodes.Create (nWifi);
NodeContainer wifiApNode = p2pNodes.Get (0); // 创建AP节点,让p2p网络中,索引为0的节点同时作为AP节点
YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); // 配置信道对象为默认参数
YansWifiPhyHelper phy = YansWifiPhyHelper::Default (); // 配置物理层对象为默认参数
phy.SetChannel (channel.Create ()); // 创建一个信道对象并与PHY对象相连,以确保所有由YansWifiPhyHelper创建的物理层对象共享相同的底层信道,即它们共享相同的无线媒介并可以相互交流干预。
WifiHelper wifi;
wifi.SetRemoteStationManager ("ns3::AarfWifiManager"); // SetRemoteStationManager()告诉helper用什么速率控制协议类型。这里是用AARF协议。
WifiMacHelper mac; // tutorial上是:NqosWifiMacHelper mac=NqosWifiMacHelper ::Default();
Ssid ssid = Ssid ("ns-3-ssid"); // 利用Ssid()方法,设置服务集标识
mac.SetType ("ns3::StaWifiMac", // 设置MAC类型为ns3::StaWifiMac
"Ssid", SsidValue (ssid),
"ActiveProbing", BooleanValue (false)); //探测请求不会发送给由这个helper创建出来的MAC层
NetDeviceContainer staDevices;
staDevices = wifi.Install (phy, mac, wifiStaNodes); //安装STA节点的mac层和物理层。
mac.SetType ("ns3::ApWifiMac", //MAC层类型为ApWifiMac
"Ssid", SsidValue (ssid));
NetDeviceContainer apDevices;
apDevices = wifi.Install (phy, mac, wifiApNode); //安装AP节点的mac层和物理层。
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator", //位置分配器类型:网格位置分配器,分配每个节点的初始位置
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0), //x轴的间隔
"DeltaY", DoubleValue (10.0),
"GridWidth", UintegerValue (3), //网格宽度
"LayoutType", StringValue ("RowFirst")); //布局类型
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel", //运动模型:在固定范围内节点以任意速度任意方向移动
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50))); //移动范围设置
mobility.Install (wifiStaNodes); //将移动模型安装在STA节点上
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); //设置AP节点的移动模型:固定
mobility.Install (wifiApNode); //在AP节点上安装移动模型
InternetStackHelper stack; //安装协议栈
stack.Install (csmaNodes);
stack.Install (wifiApNode);
stack.Install (wifiStaNodes);
Ipv4AddressHelper address; //分配IP地址
address.SetBase ("10.1.1.0", "255.255.255.0"); //p2p地址从:10.1.1.0开始
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0"); //csma地址从:10.1.2.0开始
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
address.SetBase ("10.1.3.0", "255.255.255.0"); //WiFi地址从:10.1.3.0开始
address.Assign (staDevices);
address.Assign (apDevices);
UdpEchoServerHelper echoServer (9); //csma网络中的最后一个节点作为服务器
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)); //将客户端安装在WiFi网络中的最后一个STA节点上
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Simulator::Stop (Seconds (10.0)); //仿真不会自动停止。因为AP会一直产生信标。所以,我们需要告诉仿真器暂停。
if (tracing == true)
{
pointToPoint.EnablePcapAll ("third");
phy.EnablePcap ("third", apDevices.Get (0)); //WifiHelper类中没有Enalepcap()成员函数。
csma.EnablePcap ("third", csmaDevices.Get (0), true);
}
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
编译运行:
注意!脚本中,tracing初始化为false,所以需要用cmd命令,将其改成true,然后就会在ns-3.25目录下,生成4个.pcap文件:
third-0-0.pcap:p2p中第一个节点,n0
third-0-1.pcap:wifi网络中的AP节点,n0
third-1-0.pcap:p2p中第二个节点,n1
third-1-1.pcap:csma中的第一个节点,n1
读取third-0-1.pcap文件:
为了展现STA节点在仿真过程中确实是运动的,我们连接MobilityModel航线改变追踪源。
在NS3中,tracing系统分为trace发送端和trace接收端。我们将用移动模型预定的航线改变追踪源来产生追踪事件。我们需要写一个trace接收端来与发送端相连,这样我们将得到更多的信息。
代码添加如下:
在NS_LOG_COMPONENT_DEFINE后添加:
void
CourseChange (std::string context, Ptr model)
{
Vector position = model->GetPosition();
NS_LOG_UNCOND (context <<
" x = " << position.x << ", y= " << position.y);
} //从运动模型中挑出位置信息,并且无条件地记录节点的x、y信息。
为了使客户端无线节点每次改变位置时就调用上述的函数。
在Simulator::Run前添加:
std::ostringstream oss; //输出我们想要连接的事件的追踪命名空间路径
oss <<
"/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
"/$ns3::MobilityModel/CourseChange";
Config::Connect (oss.str (), MakeCallback (&CourseChange)); //通过调用Config::Connect将节点7的追踪发送端和接收端相连,并且传递了命名空间路径
运行结果,显示了节点7的位置变化:
Yans-wifi-helper.h:
https://www.nsnam.org/docs/release/3.25/doxygen/yans-wifi-helper_8h_source.html