#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
//**这个意思是n0和n1两个节点之间是点对点通信,而n1/n2/n3/n4是csma网络。这意味着n1这个节点需要两个网络设备,一个网络设备用于点对点通信,一个用于csma网络通信。**
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
int
main (int argc, char *argv[])
{
bool verbose = true;
uint32_t nCsma = 3; //**csma网络中的节点**
CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
//**以上几行是在cmd中挂载变量 暂时不重要**
cmd.Parse (argc,argv);
if (verbose)
{
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO); //**默认开启了两个应用类的日志组件,可以在cmd中修改。**
}
nCsma = nCsma == 0 ? 1 : nCsma;
NodeContainer p2pNodes;
p2pNodes.Create (2); //**创建节点仓库p2p,并在其中放两个节点**
NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma); //**创建节点仓库csma,将节点仓库p2p中索引号为1的节点添加进仓库csma中,并且再在cmsa中创建另外的nCsma个节点**
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes); **//使用网络拓扑助手为p2p中的节点安装点对点通信环境。**
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));**//这里由函数名可知都是对信道设置属性,而不是对设备,因为ns3中的csma通信不允许一个信道上有多个不同数据率的设备。**
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes); **//使用另一个网络拓扑助手为csma中的节点安装点对点通信环境**
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)); **//给csma网络上的最后一台主机(5号节点)安装了端口号为9的服务器端程序**
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"); **//使点对点通信网络上节点产生可供网络分析的pcap文件,并以second为保存文件的前缀名**
csma.EnablePcap ("second", csmaDevices.Get (1), true); //指定csma网络上第二个节点进行sniff,true开启了混杂模式监听信道。
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
运行
如图,生成了3份pcap文件,分别是0-0,1-0,2-0,第一个数字表示网络节点号,第二个数字表示网络设备号,0-0就是0号节点的0号设备产生的数据追踪文件,1-0是1号节点的0号设备产生的数据文件,1号节点既有在点对点通信的设备也有在csma通信的设备(因此如果有csma上的其他节点给1号节点发数据,1号节点应该还会产生1-1的追踪文件。)2号节点的0号设备开启了混杂模式,所以即使数据不是发送给它的,也被它偷偷记下来了。
读取0-0的pcap文件,记录了它是PPP类型,发送UDP数据报的目的地址是10.1.2.4,端口号为9。与代码内容吻合。
读取1-0,2.0036s的时候收到了0号节点通过点对点信道传来的数据包,由于目的地址与自身不符,接着转交。
读取2-0:由于1号节点不知道10.1.2.4的mac地址,所以发送ARP请求分组,然后10.1.2.4发送响应分组报告自己的mac地址,随后1号节点通过数据链路将mac帧交给4号节点,并将信息记录在ARP缓存中。4号节点要回送信息给0号节点,也知道其在另一个网络(因为初始化了全局路由),知道要发送给1号节点又不知道MAC地址,所以也发送ARP…
ApplicationContainer serverApps2 = echoServer.Install (csmaNodes.Get (0));
serverApps2.Start (Seconds (1.0));
serverApps2.Stop (Seconds (10.0));
........
UdpEchoClientHelper echoClient2 (csmaInterfaces.GetAddress (0), 9);
echoClient2.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient2.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient2.SetAttribute ("PacketSize", UintegerValue (1024));
......
ApplicationContainer clientApps2 = echoClient2.Install (csmaNodes.Get(1));
clientApps2.Start (Seconds (2.0));
clientApps2.Stop (Seconds (10.0));
.....
csma.EnablePcap ("second", csmaDevices.Get (0), false);
增加以上几行代码,在1号节点上安装一个端口为9的服务器程序,然后将其对应的客户端程序安装到2号节点上,2号节点在csma网络中,所以它发送的消息应该是被1号节点的1号设备接收到。编译,运行。
1号节点果然生成了两份文件。
查看1-1,记录了在csma网络中由1号节点经手的数据。但是注意,2.0169的时候,1号节点才接收到4号节点传回给0号节点的数据包,而在未给2号节点安装客户端发送消息给1号节点前,1号节点是2.013的时候就接收到了,说明ns3有模拟争用。