现在的位置: 首页 > 综合 > 正文

如何在ns2中实现一个简单的网络协议

2013年01月10日 ⁄ 综合 ⁄ 共 3623字 ⁄ 字号 评论关闭

用IE不会有显示的问题Firefox有的代码显示不出来;

这篇文章适合初学者,关于初学者应该参考的文档:NS by ExampleNS2 Beginners Page都有很多实例可以参考。

本文通过实现一个简单的传输协议来说明如何在 ns2 中实现网络协议,当然,这个协议非常简单,但是在ns2 中实现协议(不是修改)的流程大体就是这个样子的了。我们称这个简单的协议做: simple_trans 协议,我们一步一步来,把 simple_trans 这个协议慢慢做的复杂。首先我想要明确一个概念:什么是在 ns2 中实现网络协议,不把这个问题搞明白我们都不知道自己在做什么。网路协议顾名思义网络上运行的协议,网络是由关系(无论什么关系)组成的,在这个网络上运行的规则(无论是优化网络数据传输还是共享网络信息)就叫做协议,所以我觉得把协议理解为强逻辑的规则是没有问题的。我们实现一个网络协议的前提是这个协议被设计出来,所以我们先要想好我们所要实现的协议是要用来做什么事情的;回到 ns2  ns2 帮我们实现好了一个框架,这个框架给我们提供了数据包初始化,链路连接,数据包传递路由等功能,也就是说我们只要搭建好我们的逻辑就可以完成协议的模拟了,在 ns2 中我们通过对数据包类型、发送数据包逻辑等等进行控制。这就好比于 ns2 给我们提供了一个铁路网,火车需要的电也有了,火车不够了还可以生产,我们在 ns2 中实现协议就是要对火车进行调度,何时到站,到站后如何运行等等就是协议的内容。

       下面就从我们的 simple_trans开始 说起,在这个协议里,首先我们要实现的任务非常简单,简单到什么程度了呢,简单到这个协议就是 a 节点对 b 节点说一句话:“ hi!, I’m a ”。不要笑,这也是一个协议。要在 ns2 上完成这个任务,我们首先要给 simple_trans 这个协议起个名字使得 ns2 可以发出这个协议的数据包并且认得这个协议发出的数据包,现在开始就是第一步了。

1,  NS_HOME/common/packet.h  enum packet中 加入协议数据包名称 PT_SIMPLE_TRANS_PACKET(必须的,注意不要加错地方,最好加在倒数第二的地方),在 class p_info 中加入name_[PT_SIMPLE_TRANS_PACKET] = "simple_trans_packet" (非必须的)。 Packet.cc 就不要动了。

2,       为了我们协议的独立性、好看性,我们在 NS_HOME 根目录下创建一个文件夹,我就叫他 kgn ,好在 kgn目录(也就是 NS_HOME/kgn )目录下给协议的主角: simple_trans.h&simple_trans.cc 。两个空文件没什么用,下面我们添加协议内容。

3,       simple_trans.h 内容:

  1. #ifndef ns_simple_trans_h  
  2. #define ns_simple_trans_h  
  3. #include "agent.h"  
  4. #include "tclcl.h"  
  5. #include "packet.h"  
  6. #include "address.h"  
  7. #include "ip.h"  
  8. #define PROTOCOL_DEFAULT_PORT 1023  
  9. #define PROTOCOL_INIT_SYN 1  


首先我们引用一些需要用到的头文件,然后我们定义了两个宏,第一个是我们 simple_trans 协议默认传输的端口(这方面如果有所疑问请参考这里 ),第二个是我们仅有的一条指令:同步指令(类似于 TCP 协议中三次握手的第一步,事实上我们的这个协议最终就是要实现一个简化版的三步握手)。继续看:

  1. struct hdr_simple_trans {  
  2.       
  3.     int type;  
  4.       
  5.     static int offset_;  
  6.     inline static int& offset() {  
  7.         return offset_;  
  8.     }  
  9.     inline static hdr_simple_trans * access(const Packet * p) {  
  10.         return (hdr_simple_trans*) p->access(offset_);  
  11.     }     
  12. };  

这些可以当做领导讲话的开头部分内容。就是定义一个我们协议的头所包括的内容,只有 type 这个是我定义的,其他的内容是 ns2 系统需要的。再继续:

  1. class simple_trans_agent : public Agent {  
  2.       
  3.     public :  
  4.         simple_trans_agent();  
  5.         virtual void recv(Packet *, Handler *);  
  6.         void send_simple_msg(int type, int target);  
  7.         int get_target(){ return simple_target; }  
  8.           
  9.     protected:  
  10.         int simple_target;  
  11.         int simple_port;  
  12.         int command(int argc, const char*const*argv);  
  13. };  

这里就是我们定义的负责“调度火车”的功能的类了。继承的是 agent 类,在 ns2 中,这个 agent 不可小觑,他是我们可以产生数据包、发送数据包、接收数据包的地方,包括的 target 变量就是数据包发送给的下一个目标。recv 函数会在仿真的过程中“自动”的收到网络上传输的数据包(更深层次的是经过了地址和端口过滤器);send_simple_msg 函数用来执行创建并发送数据的功能; get_target 就不用解释了(接口保护)。接下来是我们在协议制定过程中经常会用到的 timer 的定义, timer 顾名思义是一个定时器(闹钟)在到时时候会调用一个expire (超时)函数,这个被执行的超时函数的内容就是我们所感兴趣的,因为通过 timer 我们可以实现很多逻辑。

  1. class SYNTimer : public TimerHandler {  
  2.     public:  
  3.         SYNTimer(simple_trans_agent* t) : TimerHandler(), t_(t) {  
  4.         }  
  5.         inline virtual void expire(Event *);  
  6.     protected:  
  7.         simple_trans_agent* t_;  
  8. };  

我们只要实现 expire 函数即可, timer 的初始和使用见 simpe_trans.cc 文件:

  1. SYNTimer *syn_timer = new SYNTimer(this);  
  2. syn_timer->resched(1.00);  

resched 用来给“闹钟上弦”。

  1. void SYNTimer::expire(Event *){  
  2.       
  3.     t_->send_simple_msg(PROTOCOL_INIT_SYN, t_->get_target());  
  4.       
  5.     this->resched(1.00);  
  6. }  

expire 可以实现我们的“理想”了,譬如,我们到时了就发送我们的 SYN 信息给我们的目标节点(目标节点通过tcl 文件定义,下文中我们会见到)。

4,       simple_trans.cc 内容:

  1. int hdr_simple_trans::offset_;  
  2. static class simple_transHeaderClass : public PacketHeaderClass {  
  3.     public:  
  4.         simple_transHeaderClass() : PacketHeaderClass("PacketHeader/simple_trans",sizeof(hdr_simple_trans)) {  
  5.             bind_offset(&hdr_simple_trans::offset_);  
  6.         }  

抱歉!评论已关闭.