First.cc分析

4.2.5 Main Function
下面的脚本是:
int main (int argc, char *argv[])
{
下面两行脚本是用来使两个日志组件生效的。它们被内建在Echo Client 和Echo Server 应用中:
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
注:打开echo服务端,以及echo客户端日志,可以看到具体的信息。
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
这两行代码将回显clients和server的日志级别设为”INFO”级。这样,当仿真发生数据包发送和接受时,对应的应用就会输出相应的日志消息
4.2.6拓扑生成器
4.2.6.1 使用NodeContainer类
在我们的脚本中的下面两行将会创建ns-3节点对象,它们在仿真中代表计算机。
NodeContainer nodes;
nodes.Create (2);
节点代表一台能够加入诸如协议栈,应用以及外设卡等等的东西的计算机。上面的第一行只是声明了一个名为”nodes”的NodeContainer。第二行调用了nodes对象的Create()方法创建了两个节点。在脚本中他们所代表的节点什么都没有做。构建拓扑的下一步是把我们的节点连接到一个网络中。
4.2.6.2 使用PointToPointHelper类
我们使用拓扑生成器来完成创建,连接的底层工作。
在脚本中下面的三句话是:
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
其中第一行,
PointToPointHelper pointToPoint;
在栈中初始化了一个PointToPointHelper的对象PointToPoint。而紧接着的下一行,
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
从上层的角度告诉PointToPointHelper对象当创建一个PointToPointNetDevice对象时使用“5Mbps"来作为数据速率。
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
告诉PointToPointHelper使用"2ms"(2毫秒)作为每一个被创建的点到点信道传输延时值。
4.2.6.3 使用NetDeviceContainer类
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
会完成设备和信道的配置。PointToPointHelper的Install()方法以一个NodeContainer对象作为一个参数。在Install()方法内,一个NetDeviceContainer被创建了。当调用了pointToPoint.Install(nodes)后,我们会有两个节点,每一个节点安装了点到点网络设备,在它们之间是一个点到点信道。两个设备会被配置在一个有2毫秒传输延时的信道上以5M比特每秒的速率传输数据。
4.2.6.4 使用InternetStackHelper类
我们现在已经配置了节点和设备,但是我们还没有在节点上安装任何协议栈。下面两行代码完成这个任务:
InternetStackHelper stack;
stack.Install (nodes);
类InternetStackHelper 是一个安装PointToPointHelper 对象和点到点网络设备的网络协议栈的拓扑生成器类。其中Install()方法以一个NodeContainer 对象做为一个参数,当它被执行后,它会为每一个节点容器中的节点安装一个网络协议栈(TCP,UDP,IP等等)。
4.2.6.5 使用Ipv4AddressHelper类
下面我们需要为节点上的设备设置IP地址。我们也提供了一个拓扑生成器来管理IP地址的分配。当执行实际的地址分配时唯一用户可见的API是设置基IP地址和子网掩码。
在我们的范例脚本文件first.cc的下两行代码
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
声明了一个地址生成器对象,并且告诉它应该开始从10.1.1.0开始以子网掩码为255.255.255.0分配地址。地址分配默认是从1开始并单调的增长,所以在这个基础上第一个分配的地址n0会是10.1.1.1,紧跟着是n1:10.1.1.2等等。底层ns-3系统事实上会记住所有分配的IP地址,如果你无意导致了相同IP地址的产生,这将是一个致命的错误(顺便说一下,这是个很难调试正确的错误)。

下面一行代码,
Ipv4InterfaceContainer interfaces = address.Assign (devices);
完成了真正的地址配置。在ns-3中我们使用 Ipv4Interface对象将一个IP地址同一个设备关联起来。正如我们有时候需要一个被生成器创建的网络设备列表一样,我们有时候需要一个 Ipv4Interface对象的列表。Ipv4InterfaceContainer提供了这样的功能。
现在我们有了一个安装了协议栈,配置了IP地址类的点到点的网络。这时我们所要做的事情是运用它来产生数据通信。
4.2.7 Applications类
另一个ns-3系统的核心抽象是Application类。在这个脚本中我们用两个特定的ns-3核心 Application类:UdpEchoServerApplication和UdpEchoClientApplication。正如我们先前声明过的一样,我们使用生成器对象来帮助配置和管理潜在的对象。在这里,我们用UdpEchoServerHelper 和UdpEchoClientHelper对象使我们的工作更加容易点。
4.2.7.1 UdpEchoServerHelper类
下面在first.cc脚本中的代码被用来在我们之前创建的节点上设置一个UDP 回显服务应用。
UdpEchoServerHelper echoServer (9);
注:服务端设置端口号
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
注:将服务安装在n1上
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
上面一片代码中的第一行声明了UdpEchoServerHelper。我们并没有随机选择,而是把这个端口号作为生成器构造函数的一个参数。UdpEchoServerHelper对象有一个Install方法。实际上是这个方法的执行,才初始化回显服务器的应用,并将应用连接到一个节点上去。以nodes.Get(1)的结果作为输入,并把它作为一个未命名的NodeContainer的构造函数的参数,最终这个未命名的NodeContainer被送入Install方法中去。我们现在会看到echoServer.Install将会在管理节点的NodeContainer容器索引号为1的机节点上安装一个UdpEchoServerApplication。
应用对象需要一个时间参数来“开始”产生数据通信并且可能在一个可选的时间点“停止”。我们提供了开始和停止的两个参数。这些时间点是用ApplicationContainer的方法Start和Stop来设置的。
下面两行,
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
会使echo服务应用在1s时开始(生效)并在10s时停止(失效)。既然我们已经声明了一个模拟事件(就是应用的停止事件)在10s时被执行,模拟至少会持续10s。
4.2.7.2 UdpEchoClientHelper类
echo客户端应用的设置与回显服务器端类似。也有一个UdpEchoClientHelper来管理UdpEchoClientApplication。
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
注:interfaces.GetAddress (1),为服务器端地址即n1,9为端口号
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
注:设置发包的数量
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
注:设置发包的时间间隔
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
注:设置数据包的大小
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
注:将客户端安装在n0上面
客户端一般要设置5个属性
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
然而,对于echo客户端,我们需要设置五个不同的属性。首先两个属性是在UdpEchoClientHelper的构建过程中被设置的。按照生成器的构造函数的格式,我们把”RemoteAdress”和”RemotePort”属性传递给了生成器(实际上是作为生成器构造函数的两个必须参数传递的)。
回忆一下我们使用Ipv4InterfaceContainer来追踪我们配置给设备的IP地址。在上面的第一行代码中,我们创建了一个生成器并告诉它设置客户端的远端地址为服务器节点的IP地址。我们同样告诉它准备发送第二个数据包到端口9。那个“MaxPackets”属性告诉客户端我们所允许它在模拟期间所能发送的最大数据包个数。“Interval”属性告诉客户端在两个数据包之间要等待多长时间,而“PacketSize”属性告诉客户端它的数据包应该承载多少数据。本例中,我们让客户端发送一个1024字节的数据包。
正如echo服务端一样,我们告诉echo客户端何时来开始和停止,但是这里我们使客户端在服务端生效1s后才开始(在模拟器中时间2s的时候)。

4.2.8 Simulator类
下面我们所需要做的就是运行模拟器,这是用全局函数Simulator::Run.来做到的
Simulator::Run ();

实际上我们是在模拟器中1.0秒,2.0秒,和10.0时预设了时间的发生。当Simulator::Run被调用时,系统会开始遍历预设事件的列表并执行。首先它会在1.0s时运行事件,这个事件会使echo服务端应用生效(这个事件会预设更多的其他事件)。接下来仿真器会运行在t=2.0秒时的事件,即让echo客户端应用开始。
其实,我们只发送了一个数据包(回忆一MaxPackets属性被设置为一),在此之后,那个被单独的客户端应答请求所引发的连锁反应会停止,并且模拟器会进入空闲状态。当这发生时,生下来的事件就是服务端和客户端的Stop事件。当这些事件被执行后,就没有将来的事件来执行了,函数Simulator::Run会返回。整个模拟过程就结束了。

下面剩下的事情就是清理了。这个通过调用全局函数Simulator::Destroy来完成。
Simulator::Destroy ();
return 0;
}
./waf --run scratch/first
你应该能看到一些输出:
Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' finished successfully (0.418s)
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
这里你看到编译系统核查来确定文件被编译了,接着运行了它。你看到在echo日志构件显示了它已经发送了1024字节到在10.1.1.2的echo服务端。还可以看到回显服务器端的日志构件显示他从10.1.1.1接收到了1024字节。接下来echo服务端应答了数据包,你能看到echo客户端记录了它已经接收到了从服务端发送过来的回显数据包。
注:客户端10.1.1.1会在2s的时候发送一个数据包给服务端10.1.1.2,
服务端10.1.1.2会收到来自客户端10.1.1.1的数据包
服务端10.1.1.2会将收到来自客户端10.1.1.1的数据包返回给客户端10.1.1.1

你可能感兴趣的:(STK)