ns的安装与使用及tcl的入门学习

1 安装linux

(1)windows下删除卷,为安装linux提供空间
(2)下载ubantuISO文件,通过ultraISO刻录到U盘
(3)按照网上教程分配空间,完成linux安装

2 安装NS-2

(1)根据[https://www.cnblogs.com/wlzy/p/5962853.html]下载安装
(2)发现有错误。gcc与g++版本过高。下载5版本
(3)安装完毕,并可以通过打ns显示%,说明环境变量配置正确。
(4)不可以打开例程/home/qx/ns-allinone-2.35/ns-2.35/tcl/ex/simple.tcl,百度+谷歌,最终发现是在/usr/bin里有重复的nam,需要删除。
完毕后,终于打开了num界面,显示了simple.tcl的仿真。

3 熟悉tcl语法

(1)直接在终端输入tclsh进入交互编写程序/以文本形式保存为.tcl文件,chmod +x XXX.tcl赋予执行权限,./XXX.tcl执行
(2)仅仅支持字符串string。
行首或段首可使用#注释,行末一定要用;#注释!!!行末一定要用;#注释!!!行末一定要用;#注释!!!
基本语法格式:cmd arg1 arg2 … cmd为内置命令或过程,arg为该命令的参数,以空格或Tab分隔,以换行或分号结束。
(3)变量:set var value unset var 变量代表的值:$val
(4)字符串处理:

索引:
%string index abcd 2   
c
%string index abcd end  
d
判断:
%string is alnum abc123 
1
%string is alpha abc123 
0
匹配:
*匹配任意数量字符,?匹配一个字符,[chars]匹配指定chars内的任意一个字符
%string match a*d abcd
1
% string match a?b abc
0
% string match a??d abcd
1
% string match {[a-z][A-Z][A-Z]} aBC
1
大小:
% string length abcd
4
大小写转换:
% string toupper abcd
ABCD
% string tolower ABCDabcd
abcdabcd
% string toupper abcdabcd 3 5
abcDABcd
% string totitle abcdABCD
Abcdabcd
剪切:
% string trimright abcdabcd "cd"  
abcdab
% string trimleft abcdabcd "ab"
cdabcd
% string trim abcdabcd "a d"
bcdabc

(5)数学运算
函数:

% expr sin(3.1415926/2)
0.9999999999999997
% expr int(2.33)
2
% expr sqrt(4)
2.0
% expr rand(5)
too many arguments for math function "rand"
% expr rand()
0.6298105524060366
% expr abs(-2)
2
% expr log10(10)
1.0
% expr log(2)
0.6931471805599453
% expr pow(2,4)  
16.0
逻辑:
% expr 3^2
1
% expr 3&2
2
% 
% expr 3|2
3
% expr 3||2
1
% expr 3&&2
1
% expr 1?(2+1):(2*1)
3

操作:

% expr 4<<2
16
% expr 4>>2
1
% 
% expr 2==1
0
% expr 2!=1
1
% expr 2>1
1
% expr !2   
0
% expr ~2
-3
% expr ~(-2)    
1

(6)流控语句
if语句:

if {$x<0} {
	puts "input num $x less than 0"
} elseif  {$x==0} {
	puts "input num $x equal 0"
} else {
	puts "input num $x more than 0"
}

switch语句:

# -exact严格匹配 -glob模糊匹配/通配符 -regexp正则表达式

    switch -exact $x {
    	0 {puts "input is 0"}
    	10 {puts "input is 10"}
    	100 {puts "input is 100"}
    	default {puts "hello"}
    }
    while语句:
    root@qx-IdeaPad-U430p:/home/qx/files# cat while.tcl
    #!/usr/bin/tclsh8.5
    puts "input a num: "
    flush stdout;
    set x [gets stdin]
    set j 0
    set i 1
    while {$i<$x} {
    	set j [expr $j+$i]
    	incr i;#i加一,incr i-1为递减
    }
    puts $j
    
    root@qx-IdeaPad-U430p:/home/qx/files# chmod +x while.tcl
    root@qx-IdeaPad-U430p:/home/qx/files# ./while.tcl
    input a num: 
    10
    45

for语句:
先执行,再incr i !!!先执行,再incr i !!!先执行,再incr i !!!

root@qx-IdeaPad-U430p:/home/qx/files# cat fortest.tcl
#!/usr/bin/tclsh8.5
puts "input a num: "
flush stdout;
set x [gets stdin]
set j 0
for {set i 0} {$i<$x} {incr i} {
	set j [expr $j+$i]
}
puts "output \"j\" is $j"

root@qx-IdeaPad-U430p:/home/qx/files# chmod +x fortest.tcl
root@qx-IdeaPad-U430p:/home/qx/files# ./fortest.tcl
input a num: 
5
output "j" is 10

foreach语句:
root@qx-IdeaPad-U430p:/home/qx/files# cat foreachtest.tcl
#!/usr/bin/tclsh8.5
foreach value {1 2 3 4 5 6 7 8 9} {
	puts $value
}

root@qx-IdeaPad-U430p:/home/qx/files# chmod +x foreachtest.tcl
root@qx-IdeaPad-U430p:/home/qx/files# ./foreachtest.tcl
1
2
3
4
5
6
7
8
9

break和continue语句同C语言

(7)输入输出
输出:puts

% set var 12
12
% puts $var
12
% puts "$var"
12
% puts {$var}
$var

使用""和{}作用是不同的
puts默认输出后换行,可以使用-nonewline不换行
读入:

flush stdout;
set x [gets stdin]

(8)过程

root@qx-IdeaPad-U430p:/home/qx/files# cat proctest.tcl
#!/usr/bin/tclsh8.5
puts -nonewline "input the first num: "
flush stdout;
set x [gets stdin]
puts -nonewline "input the second num: "
flush stdout;
set y [gets stdin]
proc calvalue {var1 var2} {
        set result 1
        for {set i 0} {$i < $var2} {incr i} {
                set result [expr $result*$var1]
        }
        return $result
}
puts [calvalue $x $y]

root@qx-IdeaPad-U430p:/home/qx/files# chmod +x proctest.tcl
root@qx-IdeaPad-U430p:/home/qx/files# ./proctest.tcl
input the first num: 2
input the second num: 3
8

过程中亦可以使用global var1将var1设置为全局变量,无须使用return

(9)数组
使用set定义数组,每次定义一个元素,数组元素可以无上限。

% for {set i 0} {$i < 10} {incr i} {
	set a($i) $i    
}    	
% for {set i 0} {$i < 10} {incr i} {
	puts $a($i)  
}
0
1
2
3
4
5
6
7
8
9
可以使用unset删除数组内某个元素
% puts $a(0)
0
% unset a(0)
% puts $a(0)
can't read "a(0)": no such element in array
也可以用unset删除整个数组
% unset a
% puts $a(2)
can't read "a(2)": no such variable

(10)列表

% set b [list 0 1 2 3 4 5 6 7 8 9]
0 1 2 3 4 5 6 7 8 9

% puts [lindex $b 9]
9
% puts [lrange $b 3 7]
3 4 5 6 7
% puts [llength $b]
10

% lappend b a      
0 1 2 3 4 5 6 7 8 9 a
% set b [linsert $b 5 d]
0 1 2 3 4 d 5 6 7 8 9 a
% set b [lreplace $b 1 3 a b c]
0 a b c 4 d 5 6 7 8 9 a
% set b [lsort $b]
0 4 5 6 7 8 9 a a b c d

(11)OTcl以及类和对象(注意,OTcl需要在ns环境下,而不是前面的tclsh环境)
采用Class定义类,可以使用类名定义对象。info来查询类和对象的从属关系。

root@qx-IdeaPad-U430p:/home/qx/files# ns
% Class food
food
% food banana
banana
% food fish
fish
% food beef
beef
% banana info class
food
% food info instances
beef banana fish

类的方法定义与C++不同,可以随时增加成员函数instproc和成员变量instvar,关键字很直白嘛。
举个小例子

beef banana fish
% food instproc IS {input} {	;#整个food类来定义成员函数,使用food的对象来使用IS
	$self instvar var	;#$self代表类food本身,var为类food的成员变量
	set var $input		;#可以在函数里对变量进行各种操作,这里是直接赋值
	puts "$self is $var"	;#函数的其他操作
}
% banana IS fruit		;#调用时 对象+成员函数+参数
banana is fruit
% beef IS meat
beef is meat

类的继承
OTcl成员函数和成员变量只有public属性,即可以由子类继承。

% Class food2 -superclass food	;#food2继承food,为food的子类。
food2
% food2 apple			;同样的,food2继承了food的方法。
apple
% apple IS fruit
apple is fruit


% food2 info heritage		;#也很直白,food2是food的继承人
food Object

多继承
food2继承food,food3继承food2,且继承fish

Class food3 -superclass {food2 fish}

则调用同名成员函数时,应按照从左到右,先子后父的顺序
构造函数

food2 instproc init {args} {
	puts "class food2 initialize"
	eval $self next $args	;#next表示父类中的同名函数,这里指food的init函数
}

呼,经过一整天的学习,到这里tcl语法应该基本上够用了,一些细节可以和其他高级用法可以在实践中一边学习一边使用。

4. 第一个入门例程(网上找的)

咳咳咳,简单有线网络模型模拟,,,,,,怎么看都不简单,不过不慌,毕竟才开始使用ns第二天嘛。
先粘代码,让我分析一下。
############以下是代码######################################################
root@qx-IdeaPad-U430p:/home/qx/files/wired# cat wired.tcl

#!/usr/bin/tclsh8.5
###################################################################
######################简单有线网络模拟---六节点杠铃拓扑结构########
###################################################################
#NS 仿真模拟必须简历一个模拟对象(Simulator 类的对象)
set ns [new Simulator]

#定义不同数据流的颜色(NAM显示使用)
$ns color 1 Blue ;#1为蓝色
$ns color 2 Red  ;#2 为红色

#开启Trace跟踪文件,记录分组传送的过程
set tracefd [open wired.tr w]
$ns trace-all $tracefd
#开启NAM显示文件
set nf [open wired.nam w]
$ns namtrace-all $nf

#定义结束过程,关闭Trace文件和NAM显示文件,模拟结束时会进行调用
proc finish {} {
        global ns tracefd nf
        $ns flush-trace
        close $tracefd
        close $nf
        exit 0
}

#定义节点n0~n5
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]
set n4 [$ns node]
set n5 [$ns node]
#定义节点间的双向链路(包括带宽、时延和队列类型)
$ns duplex-link $n0 $n1 2Mb 10ms DropTail
$ns duplex-link $n1 $n2 2Mb 10ms DropTail
$ns duplex-link $n1 $n4 2Mb 20ms DropTail
$ns duplex-link $n3 $n4 2Mb 10ms DropTail
$ns duplex-link $n4 $n5 2Mb 10ms DropTail

#定义关键链路(节点1和节点4之间的链路) 的队列长度
$ns queue-limit $n1 $n4 10
#指定节点间的相互位置(节点的布局,NAM动画显示时使用)
$ns duplex-link-op $n0 $n1 orient right-down ;#定义节点1在节点0右下方
  $ns duplex-link-op $n2 $n1 orient right-up ;#定义节点1在节点2右上方
$ns duplex-link-op $n1 $n4 orient right; #定义节点4在节点1正右方
$ns duplex-link-op $n3 $n4 orient left-down; #定义节点4在节点3左下方
$ns duplex-link-op $n5 $n4 orient left-up; #定义节点4在节点5左上方
#监视关键链路的队列情况,方便NAM显示时观察
$ns duplex-link-op $n1 $n4 queuePos 0.5

#建立一个TCP链接
set tcp [new Agent/TCP]   ; #建立一个TCP发送代理
$tcp set calss_ 2
$ns attach-agent $n0 $tcp  ;#绑定TCP发送代理到节点0
set sink [new Agent/TCPSink] ;#建立一个TCP接受代理
$ns attach-agent $n5 $sink ;# 绑定TCP接收代理到节点5
$ns connect $tcp $sink   ;#链接TCP发送代理和接收代理
$tcp set fid_ 1 ;#设置TCP分组的颜色为蓝色(NAM显示时客观查)
#在TCP链接上建立FTP流
set ftp [new Application/FTP]  ;#建立一个FTP应用
$ftp attach-agent $tcp  ;#将FTP应用绑定到TCP发送代理
$ftp set type_ FTP

#建立一个UDP链接
set udp [new Agent/UDP]  ;#建立一个UDP发送代理
$ns attach-agent $n2 $udp  ;#绑定UDP发送代理到节点2
set null [new Agent/Null]  ;#建立一个UDP接收代理
$ns attach-agent $n3 $null   ;#绑定UDP接收代理到节点3
$ns  connect $udp $null   ;#链接UDP发送代理和接收代理
$udp set fid_ 2     ;#设置UDP分组的颜色为红色  (NAM显示时客观查)
#在UDP链接上建立CBR流
set cbr [new Application/Traffic/CBR] ; #建立一个CBR流应用
$cbr attach-agent $udp  ;#将CBR流应用绑定到UDP发送代理
$cbr set type_ CBR
$cbr set packet_size_ 1000  ;#设置分组大小
$cbr set rate_ 1mb         ;#设置数据速率
$cbr set random_ false

#设置代理的启动和停止时间
$ns at 0.5 "$cbr start"  ;# 设定cbr流在0.5s开始
$ns at 1.0 "$ftp start"   ;#设定ftp流在。0s开始
$ns at 9.0 "$ftp stop"   ;#设定ftp流在0.5s结束
$ns at 9.5 "$cbr stop"   ;#设定cbr流在9.5s结束

 $ns at 9.5 "$ns detach-agent $n0 $tcp; $ns detach-agent $n5 $sink"

#在模拟结束时结束过程
$ns at 10.0 "finish"

#打印CBR数据分组大小和间隔
puts "CBR packet_size_= [$cbr set packet_size_]"
puts "CBR interval = [$cbr set interval_]"

#执行模拟
$ns run

##############以上是代码#########################################
执行:
root@qx-IdeaPad-U430p:/home/qx/files/wired# ns wired.tcl
CBR packet_size_= 1000
CBR interval = 0.0080000000000000002
root@qx-IdeaPad-U430p:/home/qx/files/wired# nam wired.nam

首先,我把这个代码原原本本抄了一遍,然后运行失败了。找了很久bug,一直到了晚上才发现。
attach-agent打成了attatch-agent了,细节决定成败阿。
运行效果图如下:
Alt

trace文件的内容:

+ 1 0 1 tcp 40 ------- 1 0.0 5.0 0 63
- 1 0 1 tcp 40 ------- 1 0.0 5.0 0 63
r 1 4 3 cbr 1000 ------- 2 2.0 3.0 56 56
r 1.002 1 4 cbr 1000 ------- 2 2.0 3.0 58 58
+ 1.002 4 3 cbr 1000 ------- 2 2.0 3.0 58 58
- 1.002 4 3 cbr 1000 ------- 2 2.0 3.0 58 58
r 1.002 2 1 cbr 1000 ------- 2 2.0 3.0 61 61
+ 1.002 1 4 cbr 1000 ------- 2 2.0 3.0 61 61

这里我用more来展示,不然满屏的数据,要翻阅很久。

nam用于仿真结果可视化,trace应该是节点流量跟踪数据。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值