1. 程式人生 > 實用技巧 >使用Tcl語言配置一個簡單網路環境

使用Tcl語言配置一個簡單網路環境

1. Tcl指令碼檔案circle.tcl程式碼註釋

#設定模擬需要的一些屬性
set val(chan) Channel/WirelessChannel
set val(prop) Propagation/TwoRayGround
set val(netif) Phy/WirelessPhy
set val(mac) Mac/802_11
#將協議設定為 DSR 後,同時將佇列設定為 CMUPriQueue
set val(ifq) CMUPriQueue
set val(ll) LL
set val(ant) Antenna/OmniAntenna
set val(ifqlen) 50
#將節點個數預設為 0,待使用者輸入。此項要求使用者一定輸入,否則不執行模擬。
set val(nn) 0
set val(rp) DSR
#場景大小預設值為 1000*1000
set val(x) 1000
set val(y) 1000
#圓的半徑預設值為 400
set val(r) 400
#該過程用於在螢幕上列印在終端輸入 ns circle.tcl 後新增引數的格式
proc usage {} {
    global argv0
    puts "\nusage: $argv0 \[-nn nodes\] \[-r r\] \[-x x\] \[-y y\]\n"
    puts "note: \[-nn nodes\] is essential, and the others are optional.\n"
}
#該過程用來根據使用者的輸入更改一些預設引數的值
proc getval {argc argv} {
    global val
    lappend vallist nn r x y z
    #argc 為引數的個數,argv 為整條引數構成的字串
    for {set i 0} {$i < $argc} {incr i} {
        #變數 arg 為 argv 的第 i 部分,以空格為分界
        set arg [lindex $argv $i]
        #略過無字元“-”的字串,一般是使用者鍵入的數字
        #string range $arg m n 表示取字串$arg 的第 m 個字元到第 n 個字元
        	if {[string range $arg 0 0] != "-"} continue
        set name [string range $arg 1 end]
        #更改預設變數(節點個數,半徑,場景大小)
        set val($name) [lindex $argv [expr $i+1]]
    }
}
#呼叫 getval 過程
getval $argc $argv
#使用者沒有輸入引數,只鍵入了 ns circle.Tcl,則節點個數認為0
if { $val(nn) == 0  } {
    #列印用法
    usage
    exit
}

#建立模擬例項
set ns [new Simulator]

#設定記錄檔案
set tracefd [open circle.tr w]
$ns trace-all $tracefd
set namtracefd [open circle.nam w]
$ns namtrace-all-wireless $namtracefd $val(x) $val(y)

#關閉trace檔案並呼叫nam程式演示動畫
proc finish { } {
	global ns tracefd namtracefd
	$ns flush-trace
	close $tracefd
	close $namtracefd
	exec nam circle.nam &
	exit 0
}

set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)

create-god $val(nn)
#節點配置。由於版本原因,addressType設為def
$ns node-config -addressType def\
-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_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
    $node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
$node_($i) set Z_ 0
#設定在nam中移動節點顯示大小,否則,nam中無法顯示節點
	$ns initial_node_pos $node_($i) [expr $val(x) / 10]
}

#在node_(0)節點上建立一個UDP代理
set tcp [new Agent/UDP]
$ns attach-agent $node_(0) $tcp
#在node(0)節點沿直徑對面的節點上建立一個數據接收器
set null [new Agent/Null]
$ns attach-agent $node_([expr $val(nn)/2]) $null
#新建CBR流量發生器,分組大小500B,間隔0.05s
set cbr [new Application/Traffic/CBR]
$cbr set packetSize_ 5000
$cbr set interval_ 0.05
#連線UDP和Null
$cbr attach-agent $tcp
$ns connect $tcp $null
#在0.1s時傳送資料,3.0s時停止傳送資料,5.0s時呼叫finish過程
$ns at 0.1 "$cbr start"
$ns at 3.0 "$cbr stop"
$ns at 5.0 "finish"
$ns run

2. gawk指令碼程式碼analysis.awk註釋

BEGIN {
#設定初始變數
num_D = 0;	#丟包數
num_s = 0;	#傳送包數
num_r = 0	;	#收到包數

rate_drop = 0;	#丟包率
sum_delay = 0;	#總延遲時間
average_delay = 0;	#平均延遲時間

}
{
	#讀取trace檔案記錄
	event = $1;	#第一列為包的操作(s為傳送包,r為接收包)
	time = $2;	#第二列為操作時間
	node = $3;	#第三列為節點號
	trace_type = $4;	#第四列為操作層
	flag = $5;	#第五列為標誌位
	uid = $6;	#第六列為節點標識
	pkt_type = $7;	#第七列為包型別
	pkt_size = $8;	#第八列為包的大小

#操作
	if (event == "s" && trace_type == "AGT" && pkt_type == "cbr")
	{	send_time[uid] = time;	#建立陣列記錄發包時間
		num_s++;		#記錄傳送包總數
	}
	if (event == "r" && trace_type == "AGT" && pkt_type =="cbr")
	{	delay[uid] = time - send_time[uid];	#建立陣列記錄延遲時間
		num_r++;		#記錄收到包總數
	}
	if (event == "D" && pkt_type == "cbr")
		delay[uid] = -1;	#-1表示包丟失,該包不會記入延遲時間
}

END {
	#計算丟包數和丟包率
	num_D =num_s-num_r;	#丟包總數
	rate_drop = num_D / num_s * 100.0;	#計算丟包率
	
	#計算延遲
	for ( i = 0; i < num_s; i++)
		{if (delay[i] >= 0)
			sum_delay += delay[i];
		}#總延遲時間
	average_delay = sum_delay / num_r;	#平均延遲時間

	#列印結果
	printf("number of packets droped: %d \n",num_D);
	printf("number of packets sent: %d \n",num_s);
	printf("drop rate: %.3f%% \n",rate_drop);
	printf("average delay time: %.9f \n",average_delay);
}

3. 實驗結果

(1)
  將網路節點數設定為12,執行結果如下,生成了兩個記錄檔案nam檔案和trace檔案。



  此時的trace檔案大小為91.8kb,nam檔案大小為76.0kb。




  接下來通過gawk工具對生成的trace檔案進行分析。如果沒有安裝gawk工具,使用命令sudo apt-get install gawk進行安裝。
  結果得到網路模擬過程的丟包數、發包數、丟包率和平均延時。



(2)
  重新修改節點數為8,執行結果如下,但此時資料夾中並沒有新增額外的circle.nam和circle.tr檔案。



  檢視兩檔案的屬性,發現大小發生了改變,說明應該是新建的網路模擬環境的記錄檔案發生了覆蓋。




  同樣適用gawk對生成的trace檔案進行分析。發現隨著網路節點數的增加,導致丟包率和平均延時都增加了。