ns-2

暑假学习内容

 

       <<移动环境中三维模型差错复原传输算法研究>>这个项目中,我是做的是第二大块-模型混合传输协议的研究。而在设计此协议之前,首先要掌握网络模拟-NS2。NS2是现在学术界广泛使用的一种网络模拟软件。在设计了协议后要进行模拟,然后改进协议、再模拟,再改进。。。 直到协议达到预想的结果。

      NS2的优势在于它内容丰富,它是一个庞大的系统,目前学习资料又相对较少,特别是针对初学者的。

      首先学习TCL(tool command language)语言,TCL是一种解释执行的脚本语言。具有良好的跨平台特性和可扩展性,TCL本身是用C语言实现的,可以很方便的通过C语言进行扩充,增加新的 命令,也可以很方便的把TCL解释器嵌入你的程序中。TCL解释器也是公开源代码的。TCL目前应用非常广泛,很适合用于软件测试,跨平台的脚本应用,以 及游戏脚本。而我们的NS2写出来的代码用的OTCL,也就是在TCL上只增加了面向对象的特性。

      然后开始NS2真正的学习,先在网上找一此能运行的实例来读,比如最简单的两个节点的有线模拟代码如下:

set ns [new Simulator]

set tracefd [open example1.tr w]

$ns trace-all $tracefd

set namtracefd [open example1.nam w]

$ns namtrace-all $namtracefd

proc finish {} {

     global ns tracefd namtracefd

     $ns flush-trace

     close $tracefd

     close $namtracefd

     exec nam example1.nam &

     exit 0

}   

set n0 [$ns node]

set n1 [$ns node]

$ns duplex-link $n0 $n1 1Mb 10ms DropTail

set udp0 [new Agent/UDP]

$ns attach-agent $n0 $udp0

set cbr0 [new Application/Traffic/CBR]

$cbr0 set packetSize_ 500

$cbr0 set interval_ 0.005

$cbr0 attach-agent $udp0

set null0 [new Agent/Null]

$ns attach-agent $n1 $null0

$ns connect $udp0 $null0

$ns at 0.5 "$cbr0 start"

$ns at 4.5 "$cbr0 stop"

$ns at 5.0 "finish"

$ns run

其中:

  set ns [new Simulator] 为建立一个Simulator对象的实例,并把值赋给变量ns。

  set tracefd [open example1.tr w] 打开一个可写的example1.tr文件,用来记录模拟过程的trace数据,变量tracefd指向该文件。此数据比较重要,是我们分析具体协议的主要数据,利用此数据可以用 xgraph等软件来画出直观的图,进行分析比较。

   $ns trace-all $tracefd此句应该是具体的把数据写入example1.tr中,上面一句只是打开。

   set namtracefd [open example1.nam w] 

   $ns namtrace-all $namtracefd 这两句和上两句的比较相似,只是以nam结尾的文件是专门用来做动画演示的。

   proc finish {} 这个过程,其实就相当于c语言里面的函数。  $ns flush-trace 这是用来刷新模拟过程中所有trace对象的缓冲区。global ns tracefd namtracefd 是因为要想对这个函数外面的变量进行操作,必须用global声名这些变量。然后就是关闭文件,跟C语言差不多,有打开就有关闭。最后  exec nam example1.nam & 是执行nam,即产生动画。

    set n0 [$ns node]

    set n1 [$ns node]新建两个节点,并分别赋值给n0和n1。

    $ns duplex-link $n0 $n1 1Mb 10ms DropTail 这是在民n0和n1之间建立一个双向链接,

其带宽是1Mbit/s,延迟是10ms,队列类型为DropTail。两向双向链接其实就是两条单向链接simple-link。   

     set udp0 [new Agent/UDP]

     $ns attach-agent $n0 $udp0新建一个UDPAgent并把它绑定到n0上。

    set cbr0 [new Application/Traffic/CBR]

     $cbr0 set packetSize_ 500

     $cbr0 set interval_ 0.005

    $cbr0 attach-agent $udp0 此四句意思:第一句是建立一个cbr(constant bit rate)流量发生器,CBR(Constant Bit Rate):提供固定速率的服务,对传输延迟、传输遗失及传输跳动等服务的要求最为严质量格,适合应用于及时性或需要固定频宽的服务。所以用UDP协议最适合了。第二句是设置分组的大小为500Byte。第三句是设置发送的间隔为0.005s,即每秒发送200个分组。最后一句是把它绑定到udp0上。

  set null0 [new Agent/Null]

    $ns attach-agent $n1 $null0这两句作用是新建一个Null Agent,它是一个数据接收器

,然后把它绑定到n1上。

    $ns connect $udp0 $null0把udp0和null0两个Agent连接起来。

  $ns at 0.5 "$cbr0 start"

     $ns at 4.5 "$cbr0 stop" 这两句很明显即在0.5s 开始发送数据,在4.5s停止发送数据。

     $ns at 5.0 "finish”通知Simulator对象,在5.0s调用finish对象。

  $ns run 开始模拟。

这就是我对一个最简单的有线的udp协议网络模拟代码的理解。你可以改一此参数,看到丢包现象,我们知道,它每分钟发送200个分组,每个分组大小为500Byte,所以需要带宽大约为

:200*500*8/(1024*1024) 约等于0.8Mb/s,所以我们只要把把带改到0.5Mb/s,动画演示马上能看到丢包现象。

      上面一个程序是一个最简单的两个节点的有线网络模拟,但它是有线网络的基础,复杂的多节点的也是在此基础上添加一此东西。比如说四个节点的,代码如下:

set ns [new Simulator]

$ns color 1 Blue

$ns color 2 Red

set nf [open out.nam w]

$ns namtrace-all $nf

proc finish {} {

        global ns nf

        $ns flush-trace

        close $nf

        exec nam out.nam &

        exit 0

}

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

set n3 [$ns node]

$ns duplex-link $n0 $n2 1Mb 10ms DropTail

$ns duplex-link $n1 $n2 1Mb 10ms DropTail

$ns duplex-link $n3 $n2 1Mb 10ms SFQ

$ns duplex-link-op $n0 $n2 orient right-down

$ns duplex-link-op $n1 $n2 orient right-up

$ns duplex-link-op $n2 $n3 orient right

$ns duplex-link-op $n2 $n3 queuePos 0.5

set udp0 [new Agent/UDP]

$udp0 set class_ 1

$ns attach-agent $n0 $udp0

set cbr0 [new Application/Traffic/CBR]

$cbr0 set packetSize_ 500

$cbr0 set interval_ 0.005

$cbr0 attach-agent $udp0

set udp1 [new Agent/UDP]

$udp1 set class_ 2

$ns attach-agent $n1 $udp1

set cbr1 [new Application/Traffic/CBR]

$cbr1 set packetSize_ 500

$cbr1 set interval_ 0.005

$cbr1 attach-agent $udp1

set null0 [new Agent/Null]

$ns attach-agent $n3 $null0

$ns connect $udp0 $null0 

$ns connect $udp1 $null0

$ns at 0.5 "$cbr0 start"

$ns at 1.0 "$cbr1 start"

$ns at 4.0 "$cbr1 stop"

$ns at 4.5 "$cbr0 stop"

$ns at 5.0 "finish"

$ns run

只上跟上面的一对比,就不难发现,都差不多,只是节点现在变成了四个了

set n0 [$ns node]

set n1 [$ns node]

set n2 [$ns node]

      set n3 [$ns node]

然后还增加了节点的位置管理,$ns duplex-link-op $n2 $n3 orient right。

我想基础的有线模拟应该不是问题,参考一下别人写好的代码,然后根据自己的情况,应该可以写出来。现在主要是无线模拟,而我们的项目主要是无线模拟,前面的有线模拟只是为了了解NS2,当然也花了不少时间去理解。

       无线模拟跟有线模拟不很大的差别,它首先要配制点节点,先看一个简单的例子:

 set val(chan)   Channel/WirelessChannel

set val(prop)   Propagation/TwoRayGround

set val(netif)  Phy/WirelessPhy

set val(mac)    Mac/802_11

set val(ifq)    Queue/DropTail/PriQueue

set val(ll)     LL

set val(ant)    Antenna/OmniAntenna

set val(ifqlen) 50

set val(nn)     2

set val(rp)     AODV

set val(x)      500

set val(y)      500

set ns [new Simulator]

set tracefd [open example22.tr w]

$ns trace-all $tracefd

set namtracefd [open example22.nam w]

$ns namtrace-all-wireless $namtracefd $val(x) $val(y)

proc finish {} {

     global ns tracefd namtracefd

     $ns flush-trace

     close $tracefd

     close $namtracefd

     exec nam example22.nam &

     exit 0

}

set topo [new Topography]

$topo load_flatgrid $val(x) $val(y)

create-god $val(nn)

$ns node-config  -adhocRouting $val(rp)

           -llType $val(ll)

           -macType $val(mac)

           -ifqType $val(ifq)

           -ifqLen $val(ifqlen)

            -antType $val(ant)

           -propType $val(prop)

           -phyType $val(netif)

           -channelType $val(chan)

           -topoInstance $topo

           -agentTrace ON

           -routerTrace ON

           -macTrace OFF

           -movementTrace OFF

for {set i 0} {$i<$val(nn)} {incr i } {

     set node_($i) [$ns node]

     $node_($i) random-motion 0

}

$node_(0) set X_ 5.0

$node_(0) set Y_ 2.0

$node_(0) set Z_ 0.0

$node_(1) set X_ 390.0

$node_(1) set Y_ 385.0

$node_(1) set Z_ 0.0

$ns at 50.0 "$node_(1) setdest 25.0 20.0 15.0"

$ns at 10.0 "$node_(0) setdest 20.0 18.0 1.0"

$ns at 100.0 "$node_(1) setdest 490.0 480.0 15.0"

set tcp [new Agent/TCP]

$tcp set class_ 2

set sink [new Agent/TCPSink]

$ns attach-agent $node_(0) $tcp

$ns attach-agent $node_(1) $sink

$ns connect $tcp $sink

set ftp [new Application/FTP]

$ftp attach-agent $tcp

$ns at 10.0 "$ftp start"

for {set i 0} {$i<$val(nn)} {incr i} {

        $ns at 150.0 "$node_($i) reset";

}

$ns at 150.0 "finish"

$ns run

下面我们来看看每句话的意思,这些解释都是我从网上找的和加上自己的解理。

开始的这么一段: set val(chan)   Channel/WirelessChannel

set val(prop)   Propagation/TwoRayGround

set val(netif)  Phy/WirelessPhy

set val(mac)    Mac/802_11

set val(ifq)    Queue/DropTail/PriQueue

set val(ll)     LL

set val(ant)    Antenna/OmniAntenna

set val(ifqlen) 50

set val(nn)     2

set val(rp)     AODV

set val(x)      500

set val(y)      500

从tcl语法角度讲,肯定是定义一个val数组,设定一些模拟的属性。然后在配制节点node-config时使用, -adhocRouting $val(rp)是设定自组网(ad-hoc)中所使用的路由协议,一般有DSDVDSRTORAAODV这里使用的是AODV。-llType $val(ll)是设置移动节点的逻辑链路层(logical layer),好像都把它设置成LL。 -macType $val(mac)

是设定移动节点的MAC层(media access control layer),MAC层实现了IEEE802.11的DCF(distributed coordination function)的MAC协议。-ifqType $val(ifq)设置接口队列类型,数据从链路层到接口队列,一般为 Queue/DropTail/PriQueue。-ifqLen $val(ifqlen)设置在接口队列中最大队列的长度,这里设置为50。-antType $val(ant)设置天线模型,无线节点使用单一的全向的增益天线。一般设置为:Antenna/OmniAntenna 。-propType $val(prop)设置无线信号传输模型。这个模型用来计算信号到达接收点时的信号的强度,在移动节点的网络接口层有一个接收功率阀值,当信号强度达到此值时,接收,当小于此值时,丢弃。一般有三种设置,Free-Space、TwoRayGround、Shodowing。此处设置为: Propagation/TwoRayGround。-phyType $val(netif)这是设置网络接口类型,网络接口是无线节点访问信道的接口,这个接口通过碰撞和无线传输模块来接收其他节点发送到信道上的接口,它将传输功率、波长等写入分组头,接收节点的无线传输模块通过这些分组头信息判断是否接收这些信息,只有功率大于某个临界值时才被接收。这里一般设置成Phy/WirelessPhy 。-channelType $val(chan)设置信道类型,无线信道的功能是将分组复制给所有连接到本信道上的节点(除了源节点外)。一般设置成:Channel/WirelessChannel。

set val(nn)     2 设定节点最大个数。

set val(x)      500 设定节点拓扑的X轴最大值。

set val(y)      500 设定节点拓扑的Y轴最大值。

然后下面的一些跟有线网络一样。

set topo [new Topography]

$topo load_flatgrid $val(x) $val(y) 这两句意思很明显,是建立一个拓扑对象,范围设定在$val(x) $val(y),即500x500内。

create-god $val(nn)建立一个God对象,God对象主要是对路由协议的性能做评价,它存储了节点的总数和各节点间最短路径表等信息,这些信息通常是在模拟前就计算好的,节点的Mac对象会调用God对象。

for {set i 0} {$i<$val(nn)} {incr i } {

     set node_($i) [$ns node]

     $node_($i) random-motion 0

}

用一个for循环建立两个节点,这种方法是非常适合节点多的情况。然后关闭节点的随机运动属性,路线完全由我们指定。

$node_(0) set X_ 5.0

$node_(0) set Y_ 2.0

$node_(0) set Z_ 0.0

$node_(1) set X_ 390.0

$node_(1) set Y_ 385.0

$node_(1) set Z_ 0.0 这是设定节点的初始位置,我们都是在平面内模拟,所以z轴都是0,显然初始位置node_(0)为(5.0,2.0),node_(1)为(390.0,385.0)。

set tcp [new Agent/TCP]

$tcp set class_ 2

set sink [new Agent/TCPSink]

$ns attach-agent $node_(0) $tcp

$ns attach-agent $node_(1) $sink

$ns connect $tcp $sink这些行的意思跟有线网络差不多,先建立一个TCP Agent,下面一句$tcp set class_ 2 这好象是在条传输路线时,为了区分而加上不同的颜色,这里的2代表一种颜色,然后建立一个TCPSink Agent 这个是用来接收的,然后把节点0和TCPAgent绑定在一起,节点1和TCPSink Agent绑定在一起。

set ftp [new Application/FTP]

$ftp attach-agent $tcp

$ns at 10.0 "$ftp start"  这行的意思是建立一个应用层 的ftp,我们从网络知识可知道,

没有应用层的是产生不了流量(traffic)的 ,然后把它和TCPAgent绑定,最后一句是在10秒后开始ftp。

for {set i 0} {$i<$val(nn)} {incr i} {

        $ns at 150.0 "$node_($i) reset";

}

$ns at 150.0 "finish"

$ns run 上面这个for循环是说在150.0秒调用reset函数,即重置所有的节点,下面一句跟有线网络一样,在150.0秒调用finish函数,最后运行。

上段程序中,还有一个重要的地方就是

$ns at 50.0 "$node_(1) setdest 25.0 20.0 15.0"

$ns at 10.0 "$node_(0) setdest 20.0 18.0 1.0"

$ns at 100.0 "$node_(1) setdest 490.0 480.0 15.0"

第一句话的意思是节点1在50秒时节点以15每秒的速度向(25.0,20.0)这个点移动。因为我们把$node_($i) random-motion 置于0,即不能随机运动,所以我们要指定运动方向。下面两句话跟这一样理解。

       这样,我们一个简单的两个节点的无线模拟就算完成。跟据上面的描述,现在看下面的这个图就不难了。

以上讲的都是怎么写一个ns2中别人写好的协议的模拟的脚本,现在还有两个最重要的事情:

1>对.tr怎么分析。

2>怎么添加一个新的协议到ns2中。

1>先来看第一个问题----对.tr怎么分析。

我们进行网络模拟的目的最终是看 .tr文件里的数据。而一般.tr文件里的数据是很多很多的,而且每一行又是由很多列组成,比如第一个简单程序的.tr文件一小部分内容如下:

1     2        3   4    5      6     7    8    9    10     11   12

-    0.532  0  1   cbr    500  -------  0  0.0  1.0     4     4

r     0.534  0  1   cbr    500  -------  0  0.0  1.0     2     2

+    0.535  0  1   cbr    500  -------  0  0.0  1.0     7     7

-    0.54    0  1   cbr    500  -------  0  0.0  1.0     5     5

d     2.075  0  1   cbr    500  ------- 0  0.0  1.0    315   315

上面那1到12序号是我自己加的。

各字段意思是:

第1列的“-” 表示packet从queue中取出, ”+”表示packet放入queue中,r代表目的端收到packet。d代表queue已満,packet被drop了。

第2列表示事件发生的时间。

第3列是packet的源端(source node)

第4列是packet的目的端(destination node)

第5列是packet的类别

第6列代表packet的大小

第7列代表 packet 的 flags

第8列代表 connection(flow) 的 id

第9列代表 source address ( node.port )

第10列代表 destinations address ( node.port )

第11列代表 packet 的 sequence number ( network layer protocol's )

第12列代表 packet 的 id ( unique )

显然,这么多数据根据不同的需要,提取一些必要的信息。然后用绘图工具绘制出直观的二维曲线图,以提供我们比较和inadvertently改进协议。我们一般用的绘图的工是NS2自带的xgraph。这个绘图工具只能识别两列数,比如说:

  1 2

  2 4

  3 6 那么xgraph绘制三个点 然后连接起来,形成一个曲线,其中第一列为X轴,第二列为Y轴。所以我们必需想办法从.tr文件里提取数据,然后形成两列,以供xgrap绘图。这就要涉及awk语言。

       awk是一种用于处理文本的编程语言工具,该实用工具扫描文件中的每一行,查找与命令行中所给定 内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。也就是说它是一行-行处理。也可以处理指定每一行的各列的字段。我们以上面那组.tr文件的为例(假设它的文件名为out.tr):在linux下输入:

 awk '{print $2,$11}' out.tr >file.in

则自动创建file.in文件,打开file.in文件内容如下:

   0.532      4

   0.534      2

   0.535      7

   0.54        5

   2.075      315

即它输出了第2列和11列到file.in文件里面。然后我们用命令:xgraph file.in就能绘制出曲线图了。当然这里只是举一个简单的列子,我们要绘制的图形的数据可能更复杂,需要计算数值,这些功能awk语言都能实现,awk语言跟C语言差不多,也有if、while、for等功能。

2>看看最后一个问题----怎么添加一个新的协议到NS2中。

NS2最大的特点之一就是可扩展性,即可以添加新协议,来添加场景。比如说开NS2开始只有有线模拟,后来又添加了无线模拟。我个人认为这是NS2最难的地方,我们知道我们给定的OCTL代码来模拟,其实是调用了NS2内部的C++,所以我们要添加新协议,首先要写C++代码。一般添加新协议的步骤是(这里以tcp包头为列子说明):

1. 为packet头定义一个struct数据类型, 例如 "struct hdr_tcp"; ( 在 "~ns/tcp/tcp.h" 文件中)。

2. 实现该packet的OTcl linkage,即需要定义一个 PacketHeader 类。例如 static class TcpHeaderClass,并需要将"PacketHeader/TCP" 作为参数传给该类的构造函数; (在 "~ns/tcp/tcp.cc" 文件中)

3. 在 "~ns/common/packet.h" 文件中,为 enum packet_t 添加一个新的条目 "PT_TCP" ,并在p_into类的构造函数中添加一个新的数组元素 name[PT_TCP] = "tcp",要注意此处的位置必须对应。

4. 在文件 "~ns/tcl/lib/ns-packet.tcl" 中添加,往 "foreach prot" 中添加一行 "TCP" 。

如果新建的协议是无线路由协议,则还需要在 "~ns/tcl/lib/ns-lib.tcl" 文件中Simulator的create-wireless-node方法中添加相应的处理。当然,做了以上事情后还重新编译ns2。

 

结语:

这就是我现在的水平对NS2的理解,当然只是NS2的冰山一角,现在还是学习中。我想在设计好协议后,在添加模拟的时候碰到问题再慢慢解决。

 

 

 

via:CSDN

转载给自己看

原文地址:https://www.cnblogs.com/xlchen/p/4150621.html