构建拓扑

出处:http://blog.csdn.net/hhhparty/article/details/76595360

今天学习《ns-3 tutorial》的第6章BUILDING TOPOLOGIES。上一章介绍了怎么做最简单的点对点网络通信模拟(双机通信模拟),这一章显然要扩展网络的规模与复杂度。

6. 构建拓扑

6.1 构建一个总线型网络拓扑

这一节通过构建总线型网络这个例子,来扩展我们对NS-3网络设备和信道的认知与应用水平。NS-3提供了一种称为CSMA(即以太网csma)的网络设备和信道。这种设备模型是以以太网的基本技术为参考构建的。真实以太网采用的CSMA/CD技术,对共享信道竞争采取了指数增长的补偿竞争机制(截断的二进制指数退避方法),而NS-3内置的CSMA模型在功能上只是其子集。 
就像在上一章构建点对点拓扑时使用了工具类一样,本章的例子也有类似的工具类,帮助我们构建CSMA拓扑。NS-3提供了一个程序脚本例子,放置在examples/tutorial中,名为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
 */

#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"

// Default Network Topology
//
//       10.1.1.0
// n0 -------------- n1   n2   n3   n4
//    point-to-point  |    |    |    |
//                    ================
//                      LAN 10.1.2.0


using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");

int 
main (int argc, char *argv[])
{
  bool verbose = true;
  uint32_t nCsma = 3;

  CommandLine cmd;
  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
  cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);

  cmd.Parse (argc,argv);

  if (verbose)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }

  nCsma = nCsma == 0 ? 1 : nCsma;

  NodeContainer p2pNodes;
  p2pNodes.Create (2);

  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);

  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);

  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);

  InternetStackHelper stack;
  stack.Install (p2pNodes.Get (0));
  stack.Install (csmaNodes);

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

  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 (p2pNodes.Get (0));
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));

  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  pointToPoint.EnablePcapAll ("second");
  csma.EnablePcap ("second", csmaDevices.Get (1), true);

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

第1~23行,与first.cc类似,second.cc也是以emacs模式行、一些GPL说明、包含库等内容开始的。 
第25~31行,作者画了一个ACSII风格的文本图画,用来解释这个网络的拓扑。在second.cc中作者扩展了first.cc,除了有一个对点对点通信的nodes:n0和n1之外,n1、n2、n3、n4通过共享总线连接在一起。 
第34行,写ns3脚本时首先要引用ns3命名空间 
第35行,设置ns日志模块名字。 
第41~42行,在主函数中先定义两个变量,verbose这个bool值用于打开或关闭UdpEchoClientApplication和UdpEchoServerApplication的日志模块,默认情况下,在设置了NS_LOG_COMPONENT_DEFINE后,日志就打开了,但还是可以人为的关闭应用的日志。整数值nCsma用于设置当前LAN中node的数量。 
第44~48行,定义命令行系统对象cmd,并在命令行系统中加入用户自定义属性nCsma和verbose,使我们可以用命令行对这两个变量进行设置。 
第50~56行,定义了一些逻辑语句,根据两个变量的具体值设定程序运行特性。 
第58~59行,使用NodeContainer拓扑工具类定义一个节点容器,用于生成两个点对点网络节点。 
第61~63行,再次定义了一个节点容器,用于生成csma LAN网络节点。而且在LAN中加入的第一个节点是p2p网络中的第二个,之后又为LAN生成了数量为nCsma个的节点。那个既属于P2P也属于CSMA的node,将有两个net devices,一个是p2p的,另一个是cmsa的。 
第65~68行,与first.cc相同,我们初始化了一个P2P工具类对象,由此设置了两个Device属性:DataRate和Delay。 
第70~71行,初始化NetDeviceContainer对象,用它来跟踪P2P设备,然后使用PointToPointHelper对象将P2P devices安装到P2P的nodes上。 
第72~74行,初始化一个CsmaHelper对象,它将用来完成csma devices和Channels的生成、配置与连接。这里使用csma设置了两个信道属性DataRate和Delay。注意,这里的DataRate属性设置为Channel属性,而不是点对点里面的Device属性,这是因为在CSMA网络中不允许速率混杂(即整个LAN以某个速率通信,各节点收发速率保持一致)。这里将DataRate设为100mbps,Delay设为6560ns(任选值)。注意,设置属性时要使用相应的内置数据类型:StringValue(“100Mbps”)和TimeValue(NanoSeconds(6560))。 
第76~77行,生成一个NetDeviceContainer对象csmaDevices,用来存放安装在csma nodes上的csma Devices。 
到目前为止,我们生成了nodes、netdevices、channels,下面我们设置protocols。 
第79~81行,使用InternetStackHelper对象来安装配置协议栈。设置P2P网络地址为10.10.1.0,子网掩码255.255.255.0,还生成了Ipv4InterfaceContainer对象来存放已经分配了地址的p2p devices。 
第79~81行,使用InternetStackHelper对象来安装配置协议栈。 
第83~86行,设置P2P网络地址为10.10.1.0,子网掩码255.255.255.0,还生成了Ipv4InterfaceContainer对象来存放已经分配了地址的p2p devices。 
第88~90行,设置LAN网络地址为10.10.2.0,子网掩码255.255.255.0,还生成了Ipv4InterfaceContainer对象来存放已经分配了地址的CSMA devices。 
安装配置了协议之后,下面为node建立应用,这部分与first.cc中有很多类似。我们要在含有csma device的一个node上初始化一个Server应用,在仅含有点对点设备的node上初始化一个Client应用。 
第92~96行,先生成UdpEchoServerHelper对象用于管理server Application,参数9表示echo server application的监听端口为9。之后,建立ApplicationContainer,管理安装在csma node上的echo Server Applications,注意这里使用nCsma值为索引,使用csmaNodes.Get(nCsma)获得了第nCsma个节点(LAN中共有nCsma+1个nodes,从0计数,第0个为既有p2p设备也有csma设备的节点,1~nCsma为仅含有csma设备的节点)。之后使用serverApps.start()和stop()方法,使serverApps在第1s启动,第10s结束。 
第98~105行,先生成echoClient这个UdpEchoClientHelper对象,并分配ip地址和端口号9,之后设置echo client的属性:MaxPackets为1、Interval为1s、PacketSize为1024。之后初始化client application容器,存放安装在p2p节点上的应用echo Client,在第2s启动该应用,在第10s关闭。 
下面我们要建立某种形式的网络路由。ns-3提供了称为global routing的模型。Global routing利用了我们建立的网络在运行模拟时均可访问,且贯穿于每个节点。它可以在用户不进行配置路由器的情况下,启动路由功能。 
一般情况下,发生的情况是每个节点的行为就好像是一个OSPF router,他能即时、神奇地与幕后的所有其他路由器进行通信。每个节点生成链接广告,并直接与全局路由管理器。全局路由管理器使用全局信息为每个节点构建路由表。这需要使用一行语句: 
第107行,用于生成Ipv4GlobalRoutingHelper中PopulateRoutingTables。 
第109~110行,用于开启pcap Tracing。110行中开启csma helper的方法中,使用了一个额外的参数。由于csma网络是一个多点接入网络,意味着共享媒介上有多个端点。每个端点有一个csma网卡。有两种可互相替换的方法来Tracing这类网络。一种是为每个net device生成Tracing文件,并且只保存那些被这个设备发出或接收的数据包;另一种,选一个net device,将其设为混杂模式监听所有的数据包。这个方式就像tcpdump的工作方式。语句csma.EnablePcap (“second”, csmaDevices.Get (1), true)中最后一个参数,告诉csma helper是否安排以混杂模式捕捉数据包。 
在本例中,我们选择了csmaDevices.Get (1)这个设备,将其设置为混杂模式来sniffing网络。 
第112~114行,用于启动模拟,并在运行完毕后结束,返回0.

为了运行这个脚本,我们将second.cc拷贝到scratch目录并更名为mysecond.cc(不改就和已有的second重名了,这个可执行名已经用于ns3自身回归测试中。)

cp examples/tutorial/second.cc scratch/mysecond.cc 
./waf –run mysecond

这里写图片描述

在当前目录下,出现了second-0-0.pcap second-1-0.pcap second-2-0.pcap三个pcap文件。文件名是按照name-node-device.pcap的格式书写的。second-0-0是mysecond.cc中第一个节点第一个设备,是P2P的; second-1-0是第二个节点第一个设备,也是一个P2P的设备;second-2-0是第3个节点第0个设备,是csma的设备。最后一个设置为混杂模式,用于监听网络。下面我们用tcpdump打开pcap文件,跟踪一下网络中的echo packets。 
首先跟踪一下拓扑图中最左端节点的数据包文件: 
tcpudump命令中-nn表示直接以ip和端口显示,而不要显示主机名或域名,-tt表示打印出时间戳;-r后跟文件名,表示要打开某个pcap文件

tcpdump -nn -tt -r second-0-0.pcap 
执行结果如下: 
reading from file second-0-0.pcap, link-type PPP (PPP) 
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 
2.017607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

上面的文件,tcpdump认为其链路层是PPP协议包装的,文件内有两个数据包。

tcpdump -nn -tt -r second-1-0.pcap 
结果如下: 
reading from file second-1-0.pcap, link-type PPP (PPP) 
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

上面的文件,tcpdump认为其链路层是PPP协议包装的,文件内有两个数据包,这两个数据包与second-0-0.pcap文件中记录的一样,也即收发双方分别跟踪的结果。

tcpdump -nn -tt -r second-2-0.pcap 
结果如下: 
reading from file second-2-0.pcap, link-type EN10MB (Ethernet) 
2.007698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50 
2.007710 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50 
2.007803 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 
2.013815 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50 
2.013828 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50 
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

上面的文件,tcpdump认为其链路层是Ethernet协议包装的,有6个数据包。前两个是ARP协议广播,显然是csma LAN中为了找10.1.2.4的MAC发出的arp请求和响应。第3个包与第6个包记录了node0与node1发送的数据包(本节点node2是监听节点),第4、 5个数据包是ARP广播,为了找10.1.2.1的MAC的请求和响应。

接下来,我们增加一下csma网络中的设备数量:

./waf –run “scratch/mysecond –nCsma=4” 
结果如下: 
Waf: Entering directory /home/leo/ns-allinone-3.26/ns-3.26/build' 
Waf: Leaving directory
/home/leo/ns-allinone-3.26/ns-3.26/build’ 
Build commands will be stored in build/compile_commands.json 
‘build’ finished successfully (1.474s) 
At time 2s client sent 1024 bytes to 10.1.2.5 port 9 
At time 2.0118s server received 1024 bytes from 10.1.1.1 port 49153 
At time 2.0118s server sent 1024 bytes to 10.1.1.1 port 49153 
At time 2.02461s client received 1024 bytes from 10.1.2.5 port 9

注意,此时echo server被安装到csma节点(共4个)的最后一个,ip地址10.1.2.5. 
也许你不满意在从旁观者角度生成的跟踪文件,而是希望Tracing某一个单一设备并且对csma网络中别的数据包不感兴趣。要实现这点也很容易,可以在mysecond.cc中加入一些设置:将原来的pointToPoint.EnablePcap处语句换成下面的几行,通过指明节点号和设备号,明确Tracing的对象。

pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
   
   
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在上面的程序中,想得到node的id可以使用两种方法(要知道,nodes、devices的id都是从0开始的),一种人工指定,其中的数字是需要仔细考虑后,人为指定,类似硬编码。这种方法在大型模拟中可能会造成麻烦;第二种,就是我们现在使用的,使用NodeContainers指向ns-3 node的指针,node对象有一个GetId的方法可以返回node id,ns-3官方文档认为这个方法有利于在大型模拟中降低编程复杂度。 
一段时间后,在ns3.26目录下可能会有不少的pcap文件,如果没什么用了,就可以用下列命令清除它们:

rm *.pcap 
rm *.tr

然后我们执行修改后的程序,并将Csma节点数量增加到100:

./waf –run “scratch/mysecond –nCsma=100”

这里写图片描述

下面我们看看second-101-0.pcap的内容:

tcpdump -nn -tt -r second-101-0.pcap 
结果如下: 
reading from file second-101-0.pcap, link-type EN10MB (Ethernet) 
2.006698 ARP, Request who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50 
2.006698 ARP, Reply 10.1.2.101 is-at 00:00:00:00:00:67, length 50 
2.006803 IP 10.1.1.1.49153 > 10.1.2.101.9: UDP, length 1024 
2.013803 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101, length 50 
2.013828 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50 
2.013828 IP 10.1.2.101.9 > 10.1.1.1.49153: UDP, length 1024

6.2 模型、 属性 和 现实

This is a convenient place to make a small excursion and make an important point. 
这一节挺重要。在做模拟时,很重要的一点是,清楚的理解哪些是被模拟(建模的)的而哪些不是(出于简化模型而没考虑或采用真实源数据)。例如在上例中,我们很希望csma设备和信道都与真实Ethernet中的一样,这样模拟结果将能直接反应现实情况,但是情况并非如此(this is not the case)。 
模型(model)的定义是现实的抽象。模拟脚本的作者要负责考虑整体模拟过程的精度范围和适用领域,以及模拟的组成部件。 
在一些例子中,例如csma,可能是较为容易决定哪些没有被模拟(没有考虑)。通过读csma.h文件中的建模描述,你可以发现在csma model中没有冲突检测部分。在有些例子中,可能出现模拟中配置的行为过于简单,这与你现实中遇到的任何现实设备都不一样。所以,有必要花一些时间研究一些实例,使我们明白怎样使我们的模拟趋于真实(you can swerve outside the bounds of reality in your simulations.)。 
如我们之前所见,NS3提供了一些属性,设置这些属性能够改变model的行为。考虑一下CsmaNetDevice的两个属性:MTU和EncapsulationMode。MTU用于设置该设备的最大传输单位,也即最大的协议数据单位PDU。在CsmaNetDevice中MTU默认为1500 Bytes,这是根据RFC984设置的(“A Standard for the Transmission of IP Datagrams over Ethernet Networks.”)。对于10Base5线缆网络,MTU值最大可以为1518Bytes。如果你减去DIX封装(占18Bytes),内部以太网数据还是1500 Bytes。有时你会发现有的IEEE802.3网中的MTU设置为1492 bytes,这可能是因为LLC/SNAP封装增加了额外的8 Bytes。这两个例子显示了在不同的模拟中,要充分考虑参数的设置。 
为了设置Encapsulation Mode,CsmaNetDevice提供了一个属性称为EncapsulationMode,可以选择Dix或Llc,他们对应着以太网和LLC/SNAP两种不同的链路层帧封装。 
加入你设置Mtu为1500 Bytes并改变EncapsulationMode为Llc,那么结果是网络中每个帧最大时要封装1500字节的PDU,再加上LLC/SNAP帧头,这个帧的大小为1526 bytes,这在很多网络里是一个非法值。因为很多网络里最多每帧大小为1518 bytes。 
使情况变得复杂的是,以太网中存在jumbo帧,帧大小为1500~9000字节,而super-jumbo的帧大小>9000字节,虽然不是IEEE标准,但在有些高速Gbit网络中还是存在的。你可以把EncapsulationMode设为Dix,Mtu设为64000 bytes,csmachannel DataRate设为10 Mbps,反映出1980s款支持super-jumbo的 10Base5以太网络的基本性能,虽然这不是现实中常见的情形。 
NS3模型有很大的灵活性,许多模型将允许自由设置属性,而不是试图执行任意的一致性或特定标的规格。 
总得来说一句话,NS-3提供了很大的灵活性,使用各种Attributes来设置model行为,模拟能否真实再现现实取决于你对现实的理解和定义。(这不和没说一样么?深感写tutorial的老外也是大忽悠)

6.3 构建一个无线网络拓扑

本节我们将建立一个无线网络的模拟脚本并运行。ns-3提供了一套802.11 models,按照802.11协议做了较为精确的MAC层实现,并且按照802.11a做了一个“不太慢”的物理层模型。 
本节我们会使用wifiHelper这个工具类构建拓扑,其外观和使用方法与上面构建P2P和CSMA网络拓扑时用到的Helper类类似。 
本节所用的脚本程序在examples/tutorial/third.cc中,大部分代码是之前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
 */

#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

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

  // 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)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }

  NodeContainer p2pNodes;
  p2pNodes.Create (2);

  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);

  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);

  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);

  NodeContainer wifiStaNodes;
  wifiStaNodes.Create (nWifi);
  NodeContainer wifiApNode = p2pNodes.Get (0);

  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
  phy.SetChannel (channel.Create ());

  WifiHelper wifi;
  wifi.SetRemoteStationManager ("ns3::AarfWifiManager");

  WifiMacHelper mac;
  Ssid 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",
               "Ssid", SsidValue (ssid));

  NetDeviceContainer apDevices;
  apDevices = wifi.Install (phy, mac, wifiApNode);

  MobilityHelper mobility;

  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0),
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (5.0),
                                 "DeltaY", DoubleValue (10.0),
                                 "GridWidth", UintegerValue (3),
                                 "LayoutType", StringValue ("RowFirst"));

  mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
                             "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
  mobility.Install (wifiStaNodes);

  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (wifiApNode);

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

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

  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

  Simulator::Stop (Seconds (10.0));

  if (tracing == true)
    {
      pointToPoint.EnablePcapAll ("third");
      phy.EnablePcap ("third", apDevices.Get (0));
      csma.EnablePcap ("third", csmaDevices.Get (0), true);
    }

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189

通过看ASCII风格画,我们知道这里将拓扑的最左端加入了若干个wifi nodes,而右侧部分与second.cc中类似, 
注意,这是一个默认的网络拓扑结构,可以做为一个基础的拓扑模板,通过改变nodes数量扩展为自己所需的拓扑 
如second.cc中相同,改变参数nCsma可以改变右侧CSMA LAN中额外node的数量(不含中间那两个点对点网络的nodes)。而设置参数nWifi可以控制在一次模拟中生成多少个STA(station) nodes。无线网络里总有一个AP(ACCESS POINT)。 
在third.cc中默认了csma lan中有3个额外节点,IP地址10.1.2.2~10.1.2.4,wifi网有3个STA nodes,node 0被设为wifi AP,IP地址默认为10.1.3.2~10.1.3.4。 
在引用头文件时,本程序较之second.cc多引用了几个,如:”ns3/wifi-module.h”、 “ns3/mobility-module.h”。

生成P2P和CSMA网络nodes、net devices、channels、applications、protocols的语句就不赘述了,单讲生成wifi网络的部分: 
第97~99行,先生成一个NodeContainer对象wifiStaNodes,然后按参数nwifi值生成若干wifi nodes,然后有生成了另一个NodeContainer对象wifiApNode,并将p2p2Nodes.Get(0),也即node 0,作为wifiApNode。 
第101~103行,配置PHY和channel Helper,生成了YansWifiChannelHelper对象channel和YansWifiPhyHelper对象phy,即wifi mac层模型对象和物理层对象,之后还调用了方法phy.SetChannel(channel.Create()),用于在所有被YansWifiPhyHelper生成的PHY层对象中共享共同的channel,共享同样的无线媒介使其能够通信。 
第105~106行,生成WiFiHelper对象wifi。SetRemoteStationManager方法告诉helper选用的速率控制算法的类型。这里设置为ns3::AarfWifiManager。对于wifi MAC层,我们选择无QoS MACs。 
第108~110行,配置MAC层,wifi的SSID并且确保我们的wifi站点不执行活跃探测。 
(未完)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以通过以下步骤实现ESP32-C3上的非阻塞式UDP client循环收发: 1. 配置ESP32-C3的Wi-Fi连接。 2. 创建一个UDP套接字并设置为非阻塞模式: ```c int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); fcntl(sock, F_SETFL, O_NONBLOCK); ``` 3. 设置服务器地址和端口号: ```c struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr); ``` 4. 在一个循环中发送和接收UDP数据包: ```c while (1) { // 发送数据包 const char *msg = "Hello, server!"; sendto(sock, msg, strlen(msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); // 接收数据包 char buf[1024]; struct sockaddr_in source_addr; socklen_t socklen = sizeof(source_addr); int len = recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&source_addr, &socklen); if (len < 0 && errno != EWOULDBLOCK) { // 接收错误 } else if (len > 0) { buf[len] = '\0'; printf("Received: %s\n", buf); } // 等待一段时间 vTaskDelay(pdMS_TO_TICKS(1000)); } ``` 在该循环中,发送数据包后,使用recvfrom函数接收响应。如果没有收到响应,则继续循环。如果接收到响应,则将其打印到控制台。 请注意,为了避免出现阻塞,我们使用了O_NONBLOCK标志将套接字设置为非阻塞模式。如果在接收数据时没有收到数据包,则recvfrom函数将立即返回,并且errno将设置为EWOULDBLOCK。在这种情况下,我们只需继续循环即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值