1.文件位置
ns3/examples/tutorial/second.cc
2.程序
该程序涉及两个网络,P2P和CSMA,因此通过这个例子,大家可以学到不同网络组成的大型网络如何定以点,以及点之间的相互连接关系。
下面和第一章有所区别,第一章详细地写明了每个代码行地用处,这里是基于第一章的基础,只写了重要的部分解析。
//代码风格
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
//采用GNU许可
/*
* 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
//定义ns3命名空间
using namespace ns3;
//log组件定义
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
int
main (int argc, char *argv[])
{
//这里一直到下面,只是设置了一些初始参数和判定是否打开Log,因此只理解就可以,无需过多的占用时间。
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;
//创建p2p节点的对象
NodeContainer p2pNodes;
p2pNodes.Create (2);
//创建csma节点的对象
NodeContainer csmaNodes;
//同时也将p2p的1号节点也加入csma中
csmaNodes.Add (p2pNodes.Get (1));
csmaNodes.Create (nCsma);
//用于设置p2p的信道参数
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
//设置网卡,并安装到p2p的节点
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
//用于设置csma的信道参数
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
//设置网卡,并安装到csma的节点
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install (csmaNodes);
//向p2p的0节点和csma节点安装协议栈
InternetStackHelper stack;
stack.Install (p2pNodes.Get (0));
stack.Install (csmaNodes);
//为p2p的网卡分配IP地址
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces;
p2pInterfaces = address.Assign (p2pDevices);
//为csma的网卡分配IP地址
address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces;
csmaInterfaces = address.Assign (csmaDevices);
//设置服务端应用,安装到csma节点,并设置启动时间
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
//设置客户端应用,安装到p2p节点,并设置启动时间
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));
//设置全局路由,因为p2p网络想要连入csma网络,需要路由支持
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
//数据追踪
pointToPoint.EnablePcapAll ("second");//开启p2p类对象的pcap
csma.EnablePcap ("second", csmaDevices.Get (1), true); //开启csma类对象的pcap,用网段为1的节点进行sniff嗅探,True开启promiscuous mode 混杂模式
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
这里先看一下n1
从上面程序可以看出,n1既在p2p的点集中,又在csma的点集中;
n1的device既在p2p的device中,又在csma的device中,分配地址时也是分配了两次,只是在安装协议栈时,n1和csma一起安的。
n1涉及两个步骤:①以p2p的方式从n0接数据,并推到csma口;②从csma口接收到n4的数据,并以p2p的形式发送给n0
3.运行结果分析
这里可能会问,我咋运行的?对于刚接触ns3的,运行都会遇到困难。
运行方式包括两种:
一种在linux下直接命令行
把second脚本放到scratch,然后运行waf进行编译
./waf --run scratch/second
一种用eclipse调试(有图形界面,类似vs)
运行输出结果
At time 2s client sent 1024 bytes to 10.1.2.4 port 9
At time 2.0078s server received 1024 bytes from 10.1.1.1 port 49153
At time 2.0078s server sent 1024 bytes to 10.1.1.1 port 49153
At time 2.01761s client received 1024 bytes from 10.1.2.4 port 9
从显示的运行结果可以看出
时间 | 过程 |
---|---|
2s | client→发送1024bytes→到server(IP10.1.2.4;端口9) |
2.0078s | server→接到1024bytes→从client(IP10.1.1.1;端口 49153) |
2.0078s | server→发送1024bytes→到client(IP10.1.1.1;端口 49153) |
2.01761s | client→接到1024bytes→从server(IP10.1.2.4;端口9) |
在上层目录你会看到3个跟踪文件
3个文件的命名格式:< name >-< node >-< device >.pcap
例如:second-0-0.pcap 节点0上的设备0的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
link-type PPP (PPP):表示连接的类型为p2p
下面两个和程序运行的显示一致了
打开文件二: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
n1的连接方式是p2p(因为上面的追踪设置,对n1分别进行了p2p追踪和csma追踪)
下面两行
时间 | 过程 |
---|---|
2.003686s | n1接收到n0的数据,并将数据推到csma口 |
2.013921s | n1接收到csma口的数据,并数据交给n0 |
打开文件三: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
这里link-type EN10MB (Ethernet)代表以太网连接方式,这里时csma设置
时间 | 过程 |
---|---|
2.007698s | n1在接到n0的数据后,广播发出ARP请求,查询10.1.2.4的MAC地址 |
2.007710s | n1接到了ARP响应,告知10.1.2.4的MAC地址为06 |
2.007803s | n1向10.1.2.4发数据 |
2.013815s | n4收到数据后,广播发出ARP请求,查询n1的MAC地址 |
2.013828s | n4收到ARP响应,告知n1的MAC地址为03 |
2.013921s | n4向n1发数据 |
4.可视化输出
./waf --run second --vis