ns2協議代碼中的command理解

在之前的博文《ns2.35中嵌入自寫協議的方法》中,我們寫了一個簡單的協議,在《從hdr_ip::access()談對ns2數據包的理解》中,我們解釋了數據包的代碼編寫,本篇文章我們來說明一個問題,就是協議.cc文件中command函數的用法。

一、NS2實現一個協議的步驟

一般在NS2下實現一個協議,主要是編寫.h 和 .cc 兩個文件,但是當問題比較複雜後,可能需要編寫很多個文件,例如協議路由文件,協議特定的包(就.h),其他代碼一般都是每個 .h 文件就對應着相應的 .cc 文件。

 .h 文件,一般用於定義 數據包格式和類, 而 .cc文件,需要完成以下工作:
(1). .h中定義的類方法的實現,
(2). TclClass的編寫,爲TCL腳本提供接口, 此函數的代碼基本不變,每次只做簡單的替換即可;

static class simple_transHeaderClass : public PacketHeaderClass {
	public:
		simple_transHeaderClass() : PacketHeaderClass("PacketHeader/simple_trans",sizeof(hdr_simple_trans)) {
			bind_offset(&hdr_simple_trans::offset_);
		}
} class_simple_transhdr;

static class simple_transClass : public TclClass {
public:
	simple_transClass() : TclClass("Agent/simple_trans") {}
	TclObject* create(int, const char*const*) {
		return (new simple_trans_agent());
	}
} class_simple_trans;


(3). TCL腳本的變量和 C++ 中類的變量的綁定函數,也只直接對應着填寫即可!
(4). command 函數,是Agent類與TCL的接口,TCL腳本的命令直接作用於該函數!
(5). recv函數,是Agent類功能實現的關鍵; 網絡中對於數據包的分類、轉發和處理的操作都是通過這個函數來實現的! 參看具體的應用再編寫吧!

二、command的解釋

實現從C++類成員函數到OTCL類的成員函數之間的一一對應。
Command(int argc,const char *const*argv)

第一個參數(argc)指出命令行中的參數個數。

第二個爲命令行中的參數向量,解釋爲:argv[0]爲方法名爲“cmd”;argv[1]爲制定想要的操作;若用戶還定義了其餘參數,存於其餘argv[2…(argc-1)]中。
參數以字符串的形式給出,應先轉化爲相應的數據類型。
若操作匹配成功,返回操作結果。Command()必須返回TCL-OK,TCL-ERROR.如果操作不匹配,調用服了的command()函數,返回相應的結果,若一直到最底層的基類都不匹配,返回錯誤信號,允許子類繼承父類的命令。在多繼承的情況下,可以有兩種選擇:
1. 指定繼承父類的command()
2. 按某種順序訪問幾個父類的command(),y一找到匹配的,就返回結果,如果最終沒有找到匹配的,則返回一個錯誤信號。

直接看文字解釋很難理解,下面舉例子。

int simple_trans_agent::command(int argc, const char*const* argv) {

	if( argc == 2 ) {
		if( !strcmp( argv[1], "begin" ) ) {		

			//sendsend_simple_msg( PROTOCOL_INIT_SYN, simple_target );
			SYNTimer *syn_timer = new SYNTimer(this);
			syn_timer->resched(1.00);
			
			return (TCL_OK);		
		}
	}	
					
	if( argc == 3 ) {
		
		if( !strcmp( argv[1], "set-target" ) ) {
			
			simple_target = atoi( argv[2] );
			
			printf("=>set-target = %d \n  ", simple_target);
			
			return (TCL_OK);
		}
	}		
				
	return (Agent::command(argc, argv));
}

這裏定義了兩個命令,begin命令的使用方式是

$ns at 1.0 "$sT1 begin"
set sT1 [new Agent/simple_trans]
set-target命令的使用方式是

#$sT1 set-target [AddrParams addr2id [$n1 node-addr]]

總結就是argv[1]爲制定想要的操作命令名稱;若用戶還定義了其餘參數,存於其餘argv[2…(argc-1)]中。在set-target命令中argv[2]就是命令的唯一要傳的參數。

下面看一個更復雜的例子:

在《NS2.35中AODV+MIMC跨層信息獲取方法》一文中,有這個一個command函數

intAODV::command(int argc,constchar*const*argv){
...
else if(argc == 3) {
if(strcmp(argv[1], "index") == 0) { index = atoi(argv[2]);
return TCL_OK;
}//add by season
。。。
} else if(argc == 5) {
// cross-layer 1008 begin---------------------------------
if (strcmp(argv[1], "set-mac") == 0) {
mymac[0] = (Mac802_11 *) TclObject::lookup(argv[2]);//對 mac 對象賦初值,與表層 tcl 對應 mymac[1] = (Mac802_11 *) TclObject::lookup(argv[3]);
mymac[2] = (Mac802_11 *) TclObject::lookup(argv[4]);
for (int i=0;i<3;i++) {
if (mymac[i] == 0) {
fprintf(stderr, "MESPAgent: %s lookup %s failed.\n", argv[1], argv[2]);
return TCL_ERROR;
}
else {
printf("Get Node mac bss_id:%d \n", mymac[i]->bss_id());
// fprintf(stderr, "Get Node address .\n", nodeID);
return TCL_OK; }
} }
}
return Agent::command(argc, argv);
}

set-mac命令的用法是,可以傳入三個值

set rt($i) [$node_($i) agent 255] ;# 獲得路由層協議
$rt($i) set-mac [$node_($i) set mac_(0)] [$node_($i) set mac_(0)] [$node_($i) set mac_(0)] ;

所以無參命令argc爲2,一個參數爲3,以此類推。

理解了command後,之後文章會對ns2的離散時間機制解析,學習了之後,就可以看懂協議了。

原創文章,轉載請註明。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章