在之前的博文《ns2.35中嵌入自写协议的方法》中,我们写了一个简单的协议,在《从hdr_ip::access()谈对ns2数据包的理解》中,我们解释了数据包的代码编写,本篇文章我们来说明一个问题,就是协议.cc文件中command函数的用法。
一般在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;
实现从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)); }
$ns at 1.0 "$sT1 begin"
set sT1 [new Agent/simple_trans]set-target命令的使用方式是
#$sT1 set-target [AddrParams addr2id [$n1 node-addr]]
下面看一个更复杂的例子:
在《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 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)] ;
理解了command后,之后文章会对ns2的离散时间机制解析,学习了之后,就可以看懂协议了。