添加属于自己的应用MmApp,父类为Application,对应的OTcl类为Application/MmApp。
每一个应用都有传输层的代理来进行实际操作,因此定义一个UdpMmAgent,继承之UdpAgent,对应的OTcl类为Agent/UDP/UDPMm。
同时,要定义应用层packet header的相关信息,在packet header中加入应用相关信息,定义MultimediaHeaderClass继承之PacketHeaderClass,对应OTcl类为PacketHeader/Multimedia。
struct hdr_mm {
int ack;
int seq;
int nbytes;
double time;
int scale;//本应用的亮点,可以根据ack/Nack调整发送速率
static int offset_;
inline static int & offset() {return offset_;}
inline static hdr_mm* access(const Packet* p) {
return (hdr_mm*) p->access(offset_); }
};这些是补充到packet header当中的信息。
下面增加一个新类,向OTcl注册新类,相应的OTcl类名。绑定新添加packet header的偏移
static class MultimediaHeaderClass : public PacketHeaderClass {
MultimediaHeaderClass (): PacketHeaderClass("PacketHeader/Multimedia",siezeof(hdr_mm)) {
bind_offset(&hdr_mm::offset_);
} class_mmhdr;
让别人知道packet的类型,在packet.h中增加相应的信息。PT_NTYPE前面增加下面两句
PT_Multimedia;//在联合体中声明packet类型
name_[PT_Multimedia] = "Multimedia";//定义自己的packet类型,供别人查询
在ns-packet.tcl中增加对Multimedia的操作,add-packet-header $proc
在MmApp中实现发送
在其中包含一个定时器类,到时后条用MmApp的发送函数,发送packet出去。下面定义一个SendTimer定时器类
class SendTimer: public TimerHandler {
SendTimer(MmApp* t) : TimerHandler(), t_(t) {}
inline virtual void expire(Event*);//这个函数会执行定时器到时后的操作
MmApp* t_;}//指向对应的应用类
void SendTimer::expire(Event*) {
t_->send_mm_pkt();}//定时器到时发送packet
在MmApp类中声明包含SendTimer类。
MmApp::MmApp() : running_(0),send_timer(this),ack_timer(this) {
bind_bw("ratex_",&rate_[x]);
bind("pktsize_",&pktsize_);
bind_bool("random_",&random_);}
定义packet发送函数
void MmApp::send_mm_pkt() {
hdr_mm mh_buf;
if(running_) {
agent_->sendmsg(pktsize_, (char*) &mh_buf); //将构造好的packet header传给代理
double next_time_ = next_send_time();//计算下一个包的发送时间
if(next_time_ > 0) send_timer_.reschd(next_time_);}
}
在AppMm中实现接受
当接收端接受到一个packet时,可以根据seq nbytes等数据作出统计,设计一个定时器类ack_timer_,当其expire()时候,调用send_ack_pkt()。然后,发送端根据ack/nack信息作出发送调整。
在Agent类中增加两个函数,//Agent.h
virtual int supportMM() { return 0; }
virtual void enableMM() {}
当OTcl使用command命令时(比如把应用attach-agent到代理时),要来查询这些代理时候支持应用,尽管在UdpMmAgent已经定义了着两个函数的实现,但是仍然需要在Agent中作出声明
在App.h中为Application类增加接受信息函数
virtual void recv_msg(int ntypes,const char* msg = 0) {}
最后在ns-defualt.tcl中为新增类设置默认参数,Application/MmApp set rate0_ 0.3mb 等!
总结:
需要增加的C++源文件
mm-app.h mm-app.cc udp-mm.h udp-mm.cc
为新增加的应用packet header注册
packet.h ns-packet.tcl
在Agent.h中增加对相关应用的注册函数
supportMM() enableMM()
在App.h中为应用父类增加接受消息的函数
recv_msg()
在ns-defalt.tcl为新增加的C++类设置默认参数
为了对已有的NS增加模块,需要重新编译代码。修改Makefile,在INCLUDE目录中,添加新应用的目录,在OBJ中添加mm-app.o udp-mm.o。最后,make clean, make depend ,make
模块测试
定义代理Agent/UDP/UDPmm和应用Application/MmApp,操作类似与CBR和UDP