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的离散时间机制解析,学习了之后,就可以看懂协议了。

原创文章,转载请注明。

你可能感兴趣的:(command,ns2,Simulation,vanet)