�stepstepstepstep1111:比如我们新建的协议名字就叫做protonameprotonameprotonameprotoname,以ns2.27平台为例,我们在ns2.27目录下建立一个protoname目录。此目录包含protoname.hprotoname.hprotoname.hprotoname.h,protoname.ccprotoname.ccprotoname.ccprotoname.cc,protoname_pkt.hprotoname_pkt.hprotoname_pkt.hprotoname_pkt.h,protoname_rtable.hprotoname_rtable.hprotoname_rtable.hprotoname_rtable.h,protoname_rtable.ccprotoname_rtable.ccprotoname_rtable.ccprotoname_rtable.cc五个文件。其中五个文件的具体功能和作用如下:(1)protoname.h定义必要的计时器和路由代理(2)protoname.cc执行计时器、路由代理和Tcl文件(3)protoname_pkt.h声明protoname路由协议需要在无线自组网节点交换的数据包(4)protoname_rtable.h声明我们自己的路由选择表(5)protoname_rtable.cc执行路由选择表stepstepstepstep2222:相应文件的代码(1)protoname.h#ifndef__protoname_h__#define__protoname_h__//下面包含一些需要的头文件#includeprotoname_pkt.h//数据包报头#includeprotoname_rtable.h#includeagent.h//代理基本类#includepacket.h//数据包类#includetrace.h//跟踪类,用于在跟踪文件里记录输出的仿真结果#includetimer-handler.h//计时器基本类,创建我们自定义的计时器#includerandom.h//随机类,用于产生伪随机数#includeclassifier-port.h//端口分类器类,用于淘汰向上层传输的数据包#includemobilenode.h#includearp.h#includell.h#includemac.h#includeip.h#includedelay.h#defineCURRENT_TIMEScheduler::instance().clock()//定义了一个用于得到当前仿真时间的宏//通过一个调度类的实例完成#defineJITTER(Random::uniform()*0.5)//在0-0.5之间去随机数作为发送数据的延迟时间classProtoname;//forwarddeclaration/*Timers*///自定义计时器发送定时的控制包classProtoname_PktTimer:publicTimerHandler{public:Protoname_PktTimer(Protoname*agent):TimerHandler(){agent_=agent;}protected:Protoname*agent_;virtualvoidexpire(Event*e);};/*Agent*///定义Protoname类classProtoname:publicAgent{/*Friends*/friendclassProtoname_PktTimer;/*Privatemembers*///封装了自身的地址、内状态、路由表、可变的Tcl//以及一个负责指定输出数量的计数器nsaddr_tra_addr_;//protoname_statestate_;protoname_rtablertable_;intaccesible_var_;//用来读取Tcl代码或脚本语言u_int8_tseq_num_;protected:MobileNode*node_;PortClassifier*dmux_;//Forpassingpacketsuptoagents.端口分类器Trace*logtarget_;//Forlogging.跟踪器Protoname_PktTimerpkt_timer_;//Timerforsendingpackets.自定义计时器//内部属性inlinensaddr_t&ra_addr(){returnra_addr_;}//inlineprotoname_state&state(){returnstate_;}inlineint&accessible_var(){returnaccesible_var_;}voidforward_data(Packet*);//数据包被正确传输的目的地voidrecv_protoname_pkt(Packet*);voidsend_protoname_pkt();voidreset_protoname_pkt_timer();public:Protoname(nsaddr_t);intcommand(int,constchar*const*);voidrecv(Packet*,Handler*);//voidmac_failed(Packet*);};#endif(2)protoname.cc#includeprotoname.h#includeprotoname_pkt.h#includerandom.h#includecmu-trace.h#includeiostreaminthdr_protoname_pkt::offset_;staticclassProtonameHeaderClass:publicPacketHeaderClass{public:ProtonameHeaderClass():PacketHeaderClass(PacketHeader/Protoname,sizeof(hdr_protoname_pkt)){bind_offset(&hdr_protoname_pkt::offset_);}}class_rtProtoProtoname_hdr;staticclassProtonameClass:publicTclClass{public:ProtonameClass():TclClass(Agent/Protoname){}TclObject*create(intargc,constchar*const*argv){assert(argc==5);return(newProtoname((nsaddr_t)Address::instance().str2addr(argv[4])));}}class_rtProtoProtoname;voidProtoname_PktTimer::expire(Event*e){agent_-send_protoname_pkt();agent_-reset_protoname_pkt_timer();}Protoname::Protoname(nsaddr_tid):Agent(PT_PROTONAME),pkt_timer_(this){bind_bool(accesible_var_,&accesible_var_);ra_addr_=id;node_=(MobileNode*)Node::get_node_by_address(id);}intProtoname::command(intargc,constchar*const*argv){if(argc==2){if(strcasecmp(argv[1],start)==0){pkt_timer_.resched(0.0);returnTCL_OK;}elseif(strcasecmp(argv[1],print_rtable)==0){if(logtarget_!=0){sprintf(logtarget_-pt_-buffer(),P%f_%d_RoutingTable,CURRENT_TIME,ra_addr());logtarget_-pt_-dump();rtable_.print(logtarget_);}else{fprintf(stdout,%f_%d_Ifyouwanttoprintthisroutingtableyoumustcreateatracefileinyourtclscript,CURRENT_TIME,ra_addr());}returnTCL_OK;}}elseif(argc==3){//Obtainscorrespondingdmuxtocarrypacketstoupperlayersif(strcmp(argv[1],port-dmux)==0){dmux_=(PortClassifier*)TclObject::lookup(argv[2]);if(dmux_==0){fprintf(stderr,%s:%slookupof%sfailed\n,__FILE__,argv[1],argv[2]);returnTCL_ERROR;}returnTCL_OK;}//Obtainscorrespondingtracerelseif(strcmp(argv[1],log-target)==0||strcmp(argv[1],tracetarget)==0){logtarget_=(Trace*)TclObject::lookup(argv[2]);if(logtarget_==0)returnTCL_ERROR;returnTCL_OK;}}//PassthecommandtothebaseclassreturnAgent::command(argc,argv);}voidProtoname::recv(Packet*p,Handler*h){structhdr_cmn*ch=HDR_CMN(p);structhdr_ip*ih=HDR_IP(p);if(ih-saddr()==ra_addr()){//Ifthereexistsaloop,mustdropthepacketif(ch-num_forwards()0){drop(p,DROP_RTR_ROUTE_LOOP);return;}//elseifthisisapacketIamoriginating,mustaddIPheaderelseif(ch-num_forwards()==0)ch-size()+=IP_HDR_LEN;}//Ifitisaprotonamepacket,mustprocessitif(ch-ptype()==PT_PROTONAME)recv_protoname_pkt(p);//Otherwise,mustforwardthepacket(unlessTTLhasreachedzero)else{ih-ttl_--;if(ih-ttl_==0){drop(p,DROP_RTR_TTL);return;}forward_data(p);}}voidProtoname::recv_protoname_pkt(Packet*p){structhdr_ip*ih=HDR_IP(p);structhdr_protoname_pkt*ph=HDR_PROTONAME_PKT(p);//AllroutingmessagesaresentfromandtoportRT_PORT,//sowecheckit.assert(ih-sport()==RT_PORT);assert(ih-dport()==RT_PORT);/*...processingofprotonamepacket...*///ReleaseresourcesP