NS2安装调试详解

 目录
第一章NS2 简介··············································3
第二章NS2 仿真环境及安装注意事项····························4
第三章NS2 仿真实例··········································9
第四章NS2 总结·············································24
第一章NS2 简介
NS2(Network Simulator, version 2)是一种面向对象的用C++和Otcl 两
种开发语言进行开发的网络仿真器。它本质上是一个离散事件模拟器,本身有一
个虚拟时钟,所有的仿真都由离散事件驱动的。NS2 最初由UC Berkeley 开发而
成,最初的目的是为了研究大规模网络以及当前和未来的网络协议交互行为而开
发的。
下图是NS2 的体系结构:
网络是现代通信技术发展的产物,它把分布在不同地理区域的物理设备通过
NS 是一个用C++语言编写,以OTcl 解释器为前台面向对象的模拟器,该模
拟器支持C++中类的层次结构和OTcl 解释器中的相似层次结构,这两种层次结
构紧密相关。从用户的角度看,解释层次中的类和编译层次中的类是一一对应的。
这种层次中的基类是TclObject 类,用户通过解释器创建新的模拟对象,这些对
象先是在解释器中被实例化,然后由编译层次中相应的对象来产生映射,解释类
层次通过TclClass 类中定义的方法自动创建,用户则是通过TclObject 类中定
义的方法映射这些实例化的对象,C++代码和OTcl 脚本里面还有其它层次的类,
但这些层次并不会以TclObject 的方式被映射。
简单的说当我们要仿真一种新的协议,我们首先需要通过C++语言将协议描
述出来,这包括对协议格式的判断,对报文的处理等所有协议过程。然后我们编
写Tcl 脚本来构建一个模拟器,并且在这个模拟器中指定MAC 层,网络层等采用
我们需要仿真的协议。接下来主要是通过仿真网络行为来分析网络特性,主要包
括节点间延时统计,网络延时时间变化量统计,吞吐量统计和丢包率统计。
第二章NS2 仿真环境及安装注意事项
NS2 是一款运行在Unix/Linux 环境下的开源的网络仿真软件,根据我们的工
作习惯,我们可以在Linux 虚拟机上安装NS2,这一过程比较简单,需要注意的
是安装前需要其它几个软件包对其进行支持,这个过程网上有许多详细介绍,在
此就不多说了。我的机器上现在装的是Fedora12 的虚拟机,内核是2.6(完全
安装),NS2 的版本是最ns-allinone-2.34,运行正常。
下面主要说一下如何在WindowsXP 环境中安装NS2,这个过程比较复杂。首
先需要安装Cygwin 在WindowsXP 下模拟一个Unix/Linux 的环境,这个过程很关
键,90%以上的NS2 安装失败都是因为其Cygwin 没有安装好。
在Cygwin 的主站 http://www.cygwin.com/下载最新的安装引导程序
下载安装引导程序后双击开始安装。
点击“下一步”,选择中间的“下载但不安装”后单击“下一步”
指定将Cygwin 的安装文件下载到本地地址后单击“下一步”
选择“直接链接”下载后单击“下一步”
选择站点,在中国, http://www.cygwin.cn/号称是最快的,详细设置方法
可参考 http://www.cygwin.cn/site/install/选择好后“下一步”,这个地方要
注意,最好每次选择从同一站点下载,否则中途更换站点,他还要全部重新下载,
因为在intaller 文件夹中对下载管理文件夹是带站点的。例如从cygwin.cn 下
载的它会放到http%3a%2f%2fwww.cygwin.cn%2fpub%2f 的文件夹中
出现如图所示界面,注意红圈标注的地方,这两个地方最重要,首先要勾掉
“Hide obsolete packages”,如果不将其勾掉,很多packages 将装不上。其次
通过可以中间的小旋转符号选择“all install”, 选好后单击“下一步”。
特别注意:Cygwin 安装后,其目录下的文件不要用写字板打开,一定要用
UE 打开。因为在文件的格式上Unix 和DOS 存在一定的差异,如果在WindowsXP
下用记事本打开了,它会将Unix 格式自动转化为DOS 格式,导致下次启动Cygwin
时Bash Shell 会报错。
安装好Cygwin 后,接下来可以安装NS2 了,但是由于Cygwin 模拟的Linux
核版本的问题,不能选择最新的版本,只能选择ns-allinone-2.30。方法与Linux
安装相同,只是这个过程要比较长的时间,大概要1.5 小时吧。
这两种环境总起来说各有利弊,Cygwin+NS2,由于运行在Windows 下,启动,
调试比较方便,快捷,工作环境也比较熟悉,但是其缺点就是界面太难看了。相
比较Linux+NS2 的人机交互界面要好很多,缺点就是资源耗费很大,经常造成机
器卡机。
第三章NS2 仿真实例
NS2 安装完成后我们可以开始真正的网络仿真了,在NS2 的安装文件中已经
包含了多种类型的MAC 层,网络层,应用层协议,这包括局域网的802.11 系列,
FTP,TCP,UDP 等等,这些已有的我们可以直接调用,省去了C++编写调试步骤,
直接开始Tcl 脚本编写,构建网络。
在NS2 的安装文件下,包含了许多的例子工程,帮助初学者迅速了解NS2,
下面我们以ns-allinone-2.30\ns-2.30\tcl\ex 目录下的例程simple.tcl 为例,
简单熟悉一下NS2 仿真的过程及对如何对仿真结果进行分析。
首先对要仿真的环境做一个简单的介绍。这个网络的环境包含了四个网络节
点(n0,n1,n2,n3),如下图所示。网络节点n0 到节点n2 之间,和节点n1 到
节点n2 之间的网络频宽(bandwidth)是2Mbps,延迟时间(propagation delay)
是10ms。网络拓朴中的频宽瓶颈是在节点n2 到节点n3 之间,频宽为1.7Mbps,
延迟的时间为20ms。每个网络节点都是采用DropTail queue 的方式,且在节点
n2 到节点n3 之间的最大队列长度是10 个封包的长度。在节点n0 到n3 之间有
一条FTP 的联机,由于FTP 是架构在TCP 之上,所以在写仿真环境的描述语言的
时候,必需先建立一条TCP 的联机,在来源端n0 上使用TCP agent 产生“tcp”
发送TCP 的封包;在目的地端n3 使用TCPsink agent 产生“sink”来接受TCP
的封包、并产生回复封包(ACK)回传送端、最后把接收的TCP 封包释放。最后要
把这两个agent 连起来(connect),联机才能建立。若是没有额外的参数设定,
TCP 封包的长度为1Kbytes 。对于ns2 仿真参数内定值设定是在
ns-allinone-2.30\ns-2.30\tcl\lib 目录下的ns-default.tcl。在节点n1 到
n3 之间有一条固定的传输速率的联机(Constant Bit Rate,CBR),CBR 是架构在
UDP 之上,因此必需在n1 使用UDP agent 来产生”udp”用来发送UDP 封包,在
n3 上使用Null agent 来产生”sink”以接收由n1 传送过来的UDP 封包,然后
把接收的封包释放。CBR 的传送速度为1Mbps,每一个封包大小为1Kbytes。CBR
是在0.1 秒开始传送,在4.5 秒结束传输;FTP 是在1.0 秒开始传送,4.0 秒结
束传输。
Tcl 脚本编写如下:
# 产生一个仿真的对象
set ns [new Simulator]
#针对不同的资料流定义不同的颜色,这是要给NAM 用的
$ns color 1 Blue
$ns color 2 Red
#开启一个NAM trace file
set nf [open out.nam w]
$ns namtrace-all $nf
#开启一个trace file,用来记录封包传送的过程
set nd [open out.tr w]
$ns trace-all $nd
#定义一个结束的程序
proc finish {} {
global ns nf nd
$ns flush-trace
close $nf
close $nd
#以背景执行的方式去执行NAM
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 2Mb 10ms DropTail
$ns duplex-link $n1 $n2 2Mb 10ms DropTail
$ns duplex-link $n2 $n3 1.7Mb 20ms DropTail
#设定ns2 到n3 之间的Queue Size 为10 个封包大小
$ns queue-limit $n2 $n3 10
#设定节点的位置,这是要给NAM 用的
$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
#观测n2 到n3 之间queue 的变化,这是要给NAM 用的
$ns duplex-link-op $n2 $n3 queuePos 0.5
#建立一条TCP 的联机
set tcp [new Agent/TCP]
$tcp set class_ 2
$ns attach-agent $n0 $tcp
set sink [new Agent/TCPSink]
$ns attach-agent $n3 $sink
$ns connect $tcp $sink
#在NAM 中,TCP 的联机会以蓝色表示
$tcp set fid_ 1
#在TCP 联机之上建立FTP 应用程序
set ftp [new Application/FTP]
$ftp attach-agent $tcp
$ftp set type_ FTP
#建立一条UDP 的联机
set udp [new Agent/UDP]
$ns attach-agent $n1 $udp
set null [new Agent/Null]
$ns attach-agent $n3 $null
$ns connect $udp $null
#在NAM 中,UDP 的联机会以红色表示
$udp set fid_ 2
#在UDP 联机之上建立CBR 应用程序
set cbr [new Application/Traffic/CBR]
$cbr attach-agent $udp
$cbr set type_ CBR
$cbr set packet_size_ 1000
$cbr set rate_ 1mb
$cbr set random_ false
#设定FTP 和CBR 资料传送开始和结束时间
$ns at 0.1 "$cbr start"
$ns at 1.0 "$ftp start"
$ns at 4.0 "$ftp stop"
$ns at 4.5 "$cbr stop"
#结束TCP 的联机(不一定需要写下面的程序代码来实际结束联机)
$ns at 4.5 "$ns detach-agent $n0 $tcp ; $ns detach-agent $n3 $sink"
#在仿真环境中,5 秒后去呼叫finish 来结束仿真(这样要注意仿真环境中
#的5 秒并不一定等于实际仿真的时间
$ns at 5.0 "finish"
#执行仿真
$ns run
仿真结束后,会产生两个档案,一个是out.nam,这是给NAM 用的,用来把
仿真的过程用可视化的方式呈现出来,这可以让我们很直观的方式去了解封包传
送是如何从来源端送到接收端。另一个档案是out.tr,这个档案记录了仿真过
程中封包传送中所有的事件,例如第一笔记录是一个CBR 的封包,长度为
1000bytes,在时间0.1 秒的时候,从n1 传送到n2。这个档案对我们做效能分
析很重要,所以要先对这个档案的格式做仔细的介绍。
+ 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
- 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.108 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
- 0.108 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
r 0.114 1 2 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.114 2 3 cbr 1000 ------- 2 1.0 3.1 0 0
- 0.114 2 3 cbr 1000 ------- 2 1.0 3.1 0 0
+ 0.116 1 2 cbr 1000 ------- 2 1.0 3.1 2 2
- 0.116 1 2 cbr 1000 ------- 2 1.0 3.1 2 2
r 0.122 1 2 cbr 1000 ------- 2 1.0 3.1 1 1
+ 0.122 2 3 cbr 1000 ------- 2 1.0 3.1 1 1
.................................................................
每一笔记录的开始都是封包事件发生的原因,若是r 则表示封包被某个节点
所接收,若是+则表示进入了队列,若是-则表示离开队列,若是d 则表示封包被
队列所丢弃。接着的第二个字段表示的是事件发生的时间;字段三和字段四表示
事件发生的地点(从from node 到to node);字段五表示封包的型态;字段六是
封包的大小,字段七是封包的旗标标注;字段八表示封包是属于那一个资料流;
字段九和字段十是表示封包的来源端和目的端,这两个字段的格式是a.b,a 代
表节点编号,b 表示埠号(port number);字段十一表示封包的序号;最后字段
十二表示封包的id。以前面trace file 的第一笔为例,意思就是说有一个封包
pakcet id 为0,资料流id 为2,序号为0,长度为1000 bytes,型态为CBR,
它是从来源端1.0 要到目的地3.1,在时间0.1 秒的时候,从节点1 进入了节点
2 的队列中。
接下来,我们先简单熟悉一下awk,然后如何使用awk 去分析trace file,
以得到Throughput(吞吐量)、Delay(端点间延时)、Jitter(延时时间变化量)、
和Loss Rate(丢包率)。
awk 是一种程序语言。它具有一般程序语言常见的功能。因awk 语言具有某
些特点, 如使用直译器(Interpreter) 不需先行编译; 变量无型别之分
(Typeless),可使用文字当数组的注标(Associative Array)等特色。因此,使
用awk 撰写程序比起使用其它语言更简洁便利且节省时间。awk 还具有一些内建
功能,使得awk 擅于处理具资料列(Record),字段(Field)型态的资料;此外,
awk 内建有pipe 的功能,可将处理中的资料传送给外部的Shell 命令加以处理,
再将Shell 命令处理后的资料传回awk 程序,这个特点也使得awk 程序很容易使
用系统资源。
为便于解释awk 程序架构,以及相关的术语,我们就以上面trace file 为
例,来加以介绍。
名词介绍:
资料列:awk 从资料文件上读取的基本单位,以trace file 为例,awk 读入
的第一笔资料列为”+ 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0
0”;第二笔资料列为“- 0.1 1 2 cbr 1000 ------- 2 1.0 3.1 0
0”。一般而言,一笔资料列相当于资料文件上的一行资料。
字段:为数据列上被分隔开的子字符串。以资料列”+ 0.1 1 2 cbr
1000 ------- 2 1.0 3.1 0 0”为例,
一二三四五六七八九十十一十二
一般而言是以空格符来分隔相邻的字段。当awk 读入资料列后,会把每个字段的
值存入字段变量。
字段变量意义
$0 为一字符串, 其内容为目前awk 所读入的资料列.
$1 代表$0 上第一个字段的资料.
$2 代表$0 上第二栏个位的资料.
…… ……
程序主要节构:
Pattern1 { Actions1 }
Pattern2 { Actions2 }
……………………………
Pattern3 { Actions3 }
一般常用”关系判断式”来当成Pattern。例如:x > 3 用来判断变量x 是否
大于3,x == 5 用来判断变量x 是否等于5。awk 提供c 语言常见的关系操作
数,如:>、<、>=、<=、==、!=等等。
Actions 是由许多awk 指令所构成,而awk 的指令与c 语言中的指令非常类
似。IO 指令:print、printf( )、getline......;流程控制指令:if ( ...){...}
else{…}、while(…){…}……
在awk 程序的流程为先判断Pattern 的结果,若为真True 则执行相对应的
Actions,若为假False 则不执行相对的Actions。若是处理的过程中没有
Pattern,awk 会无条件的去执行Actions。
工作流程:
执行awk 时, 它会反复进行下列四步骤。1. 自动从指定的资料文件中读取
一笔资料列。2. 自动更新(Update)相关的内建变量之值。3. 逐次执行程序中所
有的Pattern{Actions}指令。4. 当执行完程序中所有Pattern{Actions}时,
若资料文件中还有未读取的料,则反复执行步骤1 到步骤4。awk 会自动重复进
行上述的四个步骤,所以使用者不须在程序中写这个循环。
[End-to-End Delay]
我们把测量CBR 封包端点到端点间延迟时间的awk 程序, 写在档案
measure-delay.awk 档案中。
BEGIN {
#程序初始化,设定一变量以记录目前最高处理封包的ID。
highest_packet_id = 0;
}
{
action = $1;
time = $2;
node_1 = $3;
node_2 = $4;
type = $5;
flow_id = $8;
node_1_address = $9;
node_2_address = $10;
seq_no = $11;
packet_id = $12;
#记录目前最高的packet ID
if ( packet_id > highest_packet_id )
highest_packet_id = packet_id;
#记录封包的传送时间
if ( start_time[packet_id] == 0 )
start_time[packet_id] = time;
#记录CBR (flow_id=2) 的接收时间
if ( flow_id == 2 && action != "d" ) {
if ( action == "r" ) {
end_time[packet_id] = time;
}
} else {
#把不是flow_id=2 的封包或者是flow_id=2 但此封包被drop 的时间设为-1
end_time[packet_id] = -1;
}
}
END {
#当资料列全部读取完后,开始计算有效封包的端点到端点延迟时间
for ( packet_id = 0; packet_id <= highest_packet_id; packet_id++ )
{
start = start_time[packet_id];
end = end_time[packet_id];
packet_duration = end - start;
#只把接收时间大于传送时间的记录列出来
if ( start < end ) printf("%f %f\n", start, packet_duration);
}
}
执行方法: ($为shell 的提示符号)
$awk -f measure-delay.awk out.tr
若是要把结果存到档案,可使用导向的方式。(把结果存到cbr_delay 档案中)
$awk -f measure-delay.awk out.tr > cbr_delay
执行结果:
0.100000 0.038706
0.108000 0.038706
0.116000 0.038706
0.124000 0.038706
0.132000 0.038706
………………………
[Jitter]
Jitter 就是延迟时间变化量delay variance,由于网络的状态随时都在变化,
有时候流量大,有时候流量小,当流量大的时候,许多封包就必需在节点的队列
中等待被传送,因此每个封包从传送端到目的地端的时间不一定会相同,而这个
不同的差异就是所谓的Jitter。Jitter 越大,则表示网络越不稳定。我们把量
测CBR flow 的Jitter 的awk 写在档案measure-jitter.awk 内。
BEGIN {
#程序初始化
old_time=0;
old_seq_no=0;
i=0;
}
{
action = $1;
time = $2;
node_1 = $3;
node_2 = $4;
type = $5;
flow_id = $8;
node_1_address = $9;
node_2_address = $10;
seq_no = $11;
packet_id = $12;
#判断是否为n2 传送到n3,且封包型态为cbr,动作为接受封包
if(node_1==2 && node_2==3 && type=="cbr" && action=="r") {
#求出目前封包的序号和上次成功接收的序号差值
dif=seq_no-old_seq_no;
#处理第一个接收封包
if(dif==0)
dif=1;
#求出jitter
jitter[i]=(time-old_time)/dif;
seq[i]=seq_no;
i=i+1;
old_seq_no=seq_no;
old_time=time;
}
}
END {
for (j=1; j <i ;j++)
printf("%d\t%f\n",seq[j],jitter[j]);
}
执行方法: ($为shell 的提示符号)
$awk -f measure-jitter.awk out.tr
若是要把结果存到档案,可使用导向的方式。(把结果存到cbr_jitter 档案中)
$awk -f measure-jitter.awk out.tr > cbr_jitter
执行结果:
1 0.008000
2 0.008000
3 0.008000
4 0.008000
……………………
[Loss]
我们把量测CBR Packet Loss 的情况写在档案measure-drop.awk 内。
BEGIN {
#程序初始化,设定一变量记录packet 被drop 的数目
fsDrops = 0;
numFs = 0;
}
{
action = $1;
time = $2;
node_1 = $3;
node_2 = $4;
src = $5;
flow_id = $8;
node_1_address = $9;
node_2_address = $10;
seq_no = $11;
packet_id = $12;
#统计从n1 送出多少packets
if (node_1==1 && node_2==2 && action == "+")
numFs++;
#统计flow_id 为2,且被drop 的封包
if (flow_id==2 && action == "d")
fsDrops++;
}
END {
printf("number of packets sent:%d lost:%d\n", numFs, fsDrops);
}
执行方法: ($为shell 的提示符号)
$awk -f measure-drop.awk out.tr
执行结果:
number of packets sent: 550 lost:8
这代表CBR 送出了550 个封包,但其中8 个封包丢掉了。
[Throughput]
我们把量测CBR Throughput 的情况写在档案measure-throughput.awk 内。在这
里的Throughput 是指average throughput。
BEGIN {
init=0;
i=0;
}
{
action = $1;
time = $2;
node_1 = $3;
node_2 = $4;
src = $5;
pktsize = $6;
flow_id = $8;
node_1_address = $9;
node_2_address = $10;
seq_no = $11;
packet_id = $12;
if(action=="r" && node_1==2 && node_2==3 && flow_id==2) {
pkt_byte_sum[i+1]=pkt_byte_sum[i]+ pktsize;
if(init==0) {
start_time = time;
init = 1;
}
end_time[i] = time;
i = i+1;
}
}
END {
#为了画图好看,把第一笔记录的throughput 设为零,以表示传输开始
printf("%.2f\t%.2f\n", end_time[0], 0);
for(j=1 ; j<i ; j++){
th = pkt_byte_sum[j] / (end_time[j] -
start_time)*8/1000;
printf("%.2f\t%.2f\n", end_time[j], th);
}
#为了画图好看,把第后一笔记录的throughput 再设为零,以表示传输结束
printf("%.2f\t%.2f\n", end_time[i-1], 0);
}
执行方法: ($为shell 的提示符号)
$awk -f measure-throughput.awk out.tr
若是要把结果存到档案,可使用导向的方式。(把结果存到cbr_throughput 档案
中)
$awk -f measure-throughput.awk out.tr > cbr_throughput
执行结果:
0.14 0.00
0.15 1000.00
0.15 1000.00
0.16 1000.00
……………………
最后一步就是要把量测的数据画出来。这里我们使用xgraph。
[xgraph]
在Shell 的提示符号后输入startxwin.bat,接着会出现一个新的窗口,在此窗
口输入xgraph cbr_delay,就可以把前面所存下来的档案画出来。xgraph 的运
作是把第一排当作x 轴的资料,第二排当作是y 轴的资料,然后把图给画出来。
cbr-delay 的图:
在一刚开始的时候,由于只有CBR 的封包,所以End-to-End Delay Time 都是固
定的,但在1.0 秒后,网络多了FTP 的封包,这使得CBR 封包和FTP 封包必须互
相的抢夺网络的资源,因此End-to-End Delay Time 变得不在固定,但等到FTP
传输结束后,CBR 封包的End-to-End Delay Time 又变成是固定值了。
cbr-jitter 的图:
Jitter 的变化情况跟End-to-End 的原因是相同的,都是由于FTP 封包的加入才
会指得End-to-End Delay Time 会产生变化。
cbr-throughput 的图:
从图可以很清楚地看出,从0.1 秒到4.5 秒,CBR 的传输速率大都维持在1Mbps。
第四章NS2 总结
通过上面的例子我们可以看到NS2 仿真网络的一个大概的过程,在这个过程
中,我们首先需要创建网络中的节点,然后为节点定义物理层特性,包括带宽,
延时,调度机制等等,准确的描述网络的物理层特性是非常重要的,这会直接影
响仿真的结果。
接下来我们描述网络层及之上的应用层,这些由于是调用NS2 已有的,所以
我们不再需要自己编写调试C++,但如果是仿真新的协议,那么这部分一定要做
到对协议精准的理解,解释。要描述完整协议过程。
最后仿真并分析数据,这部分相对简单点,主要是使用几款工具。需要熟练
掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值