开始读代码
# 总代码注释:
* Classical hidden terminal problem and its RTS/CTS solution.
*
* * Topology: [node 0] <-- -50 dB --> [node 1] <-- -50 dB --> [node 2]
* * This example illustrates the use of
* - Wifi in ad-hoc mode
*
* - Matrix propagation loss model
*
* - Use of OnOffApplication to generate CBR stream
*
* - IP flow monitor
*
了解经典隐终端问题及其RTS/CTS解决方案是什么,移步: RTS如何解决隐终端问题的?
系统模型图
NS3的基本模型:
隐终端系统模型图
拓扑结构: [node 0] <-- -50 dB --> [node 1] <-- -50 dB --> [node 2]
为什么使用Ad-hoc?
Ad-hoc是什么?
不需要接入点(Access Point),各无线设备以点对点的方式进行直接通信的方式。它也被称为多跳无线网、自组织网络或无固定设施的网络。 重要特点:
- Ad hoc网络是一种特殊的无线移动网络(本质)。网络中所有结点的地位平等,无需设置任何的中心控制结点。网络中的结点不仅具有普通移动终端所需的功能,而且具有报文转发能力。
网络中的节点既可以当做通信的主机,又可以代表路由器,为其他主机中继数据包。移动自组网可以成为一个独立的网络存在(如图1所示),也可以通过网关与互联网连接(如图2所示)
Ad-hoc与我们的系统模型的联系?
我们知道节点传播范围是有限的。当我们的两个节点距离较远的时候。比如Node 0和Node 2,则我们可以通过中间节点Node 1使得两者之间通信。这种传播模式只有在ad-hoc上面才能实现。
为什么使用Matrix propagation loss model矩阵传播损耗模型?
传播模型是和channel直接挂钩的,它用来确定接收机能够接收到信号的强度。 传播模型比较 一般评价模型的方式包括计算复杂度以及影响传输的效果。NS-3已经有了16种这样的模型。这么多,如何选择呢? 从可用的角度,我们可以评估他们的计算复杂度以及仿真中如何影响传输的正确率。然而准确性评估有个问题,模型是用来适配实际环境的,而环境千变万化,偏差在所难免。可以粗略看一下每一种模型如何影响数据传输结果来确定使用哪一种传播模型最合适。 本文当中我们使用矩阵传播损耗模型,当传播的损耗为50db时,两个节点能够互相收发信息。当传播的损耗到达200db以上的时候,两个节点信号微弱,无法检测到信号。
CBR流
CBR(Constants Bit Rate)即固定码率,就是恒定比特率的意思。CBR是一种固定采样率的压缩方式。优点是压缩快,能被大多数软件和设备支持,缺点是占用空间相对大,效果不十分理想,现已逐步被VBR的方式取代。
OnOffApplication:OnOff应用是个开关应用,开的时候产生流量,关的时候不产生流量。
重要的函数experiment
函数的输入输出与功能?
void experiment (bool enableCtsRts, std::string wifiManager)
输入:
enableCtsRts是否启用RTS/CTS协议、
wifiManager流量管理,设置远程站点管理器,(模式Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, Onoe, Rraa,命令行交互控制)
功能:
模拟有和没有RTS/CTS协议执行情况下,通过建立对flow1和flow2两条流量监控的模式,观察节点间收发的情况。
在main函数中加入ns3::LogLevel level = (enum ns3::LogLevel)(LOG_LEVEL_ALL|LOG_PREFIX_ALL); LogComponentEnable (“XXXXXXXXXXXXX”,level); 可以显示时间,节点等等,全部信息
运行结果如何?
不启用RTS/CTS协议,节点收发情况。 启用RTS/CTS协议,节点收发情况。 throughput:一般指吞吐量。 吞吐量是指对网络、设备、端口、虚电路或其他设施,单位时间内成功地传送数据的数量(以比特、字节、分组等测量)。
代码如何实现我们的系统模型仿真?
首先,我们回顾一下NS3建立网络模型的基本流程,代码可以参考first.cc点对点通信。
NS3建立网络模型的基本流程
简单读一下first.cc回顾NS3脚本编写的流程
- 头文件
- 名字空间(using namespace ns3)
- 允许脚本使用Log系统中的宏定义打印辅助信息。
- Main()函数中的准备工作,如读取命令行参数,设置最小模拟时间单元,开启Log组件等。
- 创建网络拓扑,Node,Channel,EntDevice。创建节点,配置信道属性,创建信道并连接节点。
- 安装TCP/IP协议簇
- 安装应用程序:Application,有很多不同的分组收发定义,如BulkSendApplication使用了贪恋分组发送模型OnOffApplication使用了ON/OFF分组发送模型。
- 数据生成
- 启动与结束
知道了以上流程后,我们分块来看看代码是如何实现这些流程的?
输入enableCtsRts 设置启用协议的阈值: 是否启用RTS/CTS协议(超过阈值则开启,所以设置阈值,小的为100开启,大的为2200不开启)
UintegerValue ctsThr = (enableCtsRts ? UintegerValue (100) : UintegerValue (2200));
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", ctsThr);
创建网络拓扑:
- 创建网络节点
NodeContainer nodes;
nodes.Create (3);
移动模块,为节点添加移动属性,使得其模型更有普适性
for (uint8_t i = 0; i < 3; ++i)
{
nodes.Get (i)->AggregateObject (CreateObject<ConstantPositionMobilityModel> ());
}
- 配置信道属性,创建信道并连接节点(需要调用网络模块)
Wifi网络设备包括链路层(WifiMac)与物理层(WifiPhy)部分。这里的wifiNetDevice只起一个连接上下层协议的桥梁作用,没有什么实质性的功能。主
Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel> ();
lossModel->SetDefaultLoss (200);
lossModel->SetLoss (nodes.Get (0)->GetObject<MobilityModel> (), nodes.Get (1)->GetObject<MobilityModel> (), 50);
lossModel->SetLoss (nodes.Get (2)->GetObject<MobilityModel> (), nodes.Get (1)->GetObject<MobilityModel> (), 50);
Ptr<YansWifiChannel> wifiChannel = CreateObject <YansWifiChannel> ();
wifiChannel->SetPropagationLossModel (lossModel);
wifiChannel->SetPropagationDelayModel (CreateObject <ConstantSpeedPropagationDelayModel> ());
WifiHelper wifi;
wifi.SetStandard (WIFI_STANDARD_80211b);
wifi.SetRemoteStationManager ("ns3::" + wifiManager + "WifiManager");
YansWifiPhyHelper wifiPhy;
wifiPhy.SetChannel (wifiChannel);
WifiMacHelper wifiMac;
wifiMac.SetType ("ns3::AdhocWifiMac");
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, nodes);
安装TCP/IP协议簇,分配地址
InternetStackHelper internet;
internet.Install (nodes);
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.0.0.0", "255.0.0.0");
ipv4.Assign (devices);
安装应用
- 将通道用CBR流填充
- 服务器端开启OnOffApplication应用
- OnOffApplication:OnOff应用是个开关应用,开的时候产生流量,关的时候不产生流量。
ApplicationContainer cbrApps;
uint16_t cbrPort = 12345;
OnOffHelper onOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.0.0.2"), cbrPort));
onOffHelper.SetAttribute ("PacketSize", UintegerValue (1400));
onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
onOffHelper.SetAttribute ("DataRate", StringValue ("3000000bps"));
onOffHelper.SetAttribute ("StartTime", TimeValue (Seconds (1.000000)));
cbrApps.Add (onOffHelper.Install (nodes.Get (0)));
onOffHelper.SetAttribute ("DataRate", StringValue ("3001100bps"));
onOffHelper.SetAttribute ("StartTime", TimeValue (Seconds (1.001)));
cbrApps.Add (onOffHelper.Install (nodes.Get (2)));
- UDP 构建一个udp应用,客户端往服务器端发数据。可以设置数据包的大小,数量,发送间隔。
- applications的作用:为了说明时间错开的情况下,0、1不会冲突。当我们监视flowID这个变量的时候,可以发现,刚开始发送的两个包也就是flowID1和flowID2可以成功被node1接收到,说明系统本身接收和发送是没有问题的。为了更好地对比使用RTS/CTS协议和不使用情况下的运行情况。也是为了解决ARP协议的一些bug。
uint16_t echoPort = 9;
UdpEchoClientHelper echoClientHelper (Ipv4Address ("10.0.0.2"), echoPort);
echoClientHelper.SetAttribute ("MaxPackets", UintegerValue (1));
echoClientHelper.SetAttribute ("Interval", TimeValue (Seconds (0.1)));
echoClientHelper.SetAttribute ("PacketSize", UintegerValue (10));
ApplicationContainer pingApps;
echoClientHelper.SetAttribute ("StartTime", TimeValue (Seconds (0.001)));
pingApps.Add (echoClientHelper.Install (nodes.Get (0)));
echoClientHelper.SetAttribute ("StartTime", TimeValue (Seconds (0.006)));
pingApps.Add (echoClientHelper.Install (nodes.Get (2)));
执行时序图
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll ();
开始仿真
Simulator::Stop (Seconds (10));
Simulator::Run ();
|