OMnet++仿真dsdv路由协议

期末了,怕老师偷袭检查大作业,快速搞了搞实验,花了几天看了看c++,又花了一两天看omnet++的使用和tictoc例程。开始写,记录一下。(菜鸟的记录)


项目目录如下:

table文件:路由表及相关操作

dsdv_table文件:路由之间传递的链路信息及相关操作

data文件:模拟发送的分组

dsdvnet.cpp:路由类的相关操作

dsdvnet.ned:模块属性和网络拓扑描述

omnetpp.ini:仿真设置


dsdvnet.ned:

simple DsdvHost

{

@display("i=device/pc_s");

gates:

inout gate[];

}//路由模块,gates设成inout双向,gate[ ]形式使门的数量根据拓扑改变

network Dsdvnet

{

types:

channel Channel extends ned.DelayChannel {

delay = 100ms;

}//定义延迟为100ms的链路

submodules:

dsdvhost[10]:DsdvHost;//定义10个主机

connections:

dsdvhost[0].gate++ <--> Channel <--> dsdvhost[1].gate++;

dsdvhost[1].gate++ <--> Channel <--> dsdvhost[2].gate++;

dsdvhost[1].gate++ <--> Channel <--> dsdvhost[4].gate++;

dsdvhost[3].gate++ <--> Channel <--> dsdvhost[4].gate++;

dsdvhost[4].gate++ <--> Channel <--> dsdvhost[5].gate++;

dsdvhost[6].gate++ <--> Channel <--> dsdvhost[0].gate++;

dsdvhost[7].gate++ <--> Channel <--> dsdvhost[4].gate++;

dsdvhost[8].gate++ <--> Channel <--> dsdvhost[4].gate++;

dsdvhost[9].gate++ <--> Channel <--> dsdvhost[8].gate++;

dsdvhost[8].gate++ <--> Channel <--> dsdvhost[2].gate++;

dsdvhost[5].gate++ <--> Channel <--> dsdvhost[3].gate++;

}

 简单的了解下:ned构建网络拓扑时,是从上到下构建的。dsdvnet构建时,先设好submodule和connections,这个时候就知道每个submodule需要多少个gate。

得到的仿真时拓扑如图:


omnetpp.ini:

[General]

record-eventlog = true

[Config Dsdvnet]

network =Dsdvnet

 record-eventlog = true可以在仿真完成后产生记录事件的文件,如下图,位置在results文件夹


table.h:

#ifndef TABLE_H_
#define TABLE_H_
#define MAXSIZE 20
#include "dsdv_table_m.h"

typedef struct{
    int destination; //目的主机
    int nextgate; //下一跳走的gate
    int nextnode; //下一个主机
    int metric; //路径代价
    int seq_no; //目的主机的序号
}table;

class Table{
public:
    table T[MAXSIZE];
    int length=0;

    bool addTable(const table* t); //新加一个表项
    bool deleteTable(int index); //删除一个表项
    int findTable(int dest); //找到表项对应的位置
    int campare(int index,const table* t); //和原路径相比较,如果不需要更新,返回0;要添加表项,返回2;删除表项,返回-1;更改表项,返回1
    void renewTable(const table* t);//根据t的值更行路由表表
    void renewItem(int index,const table* t);//更新表项
    void copytotable(int index,const dsdv_table *msg);
    void copytomsg(int index,dsdv_table *msg);//将表项复制给msg消息
    void printTable();//打印路由表
};

#endif /* TABLE_H_ */

table.c:

#include <stdio.h>
#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;

#include "table.h"

bool Table::addTable(const table* t){
    if(this->length==MAXSIZE)
        return false;//如果超过表最大长度,返回false

    this->T[this->length].destination=t->destination;
    this->T[this->length].metric=t->metric;
    this->T[this->length].nextgate=t->nextgate;
    this->T[this->length].nextnode=t->nextnode;
    this->T[this->length].seq_no=t->seq_no;
    this->length++;//将表项添加到表中,表长+1

    return true;
}

bool Table::deleteTable(int index){
    if(index>=length||index<0){
        return false;
    }//如果index超过表长,或index小于0,返回false

    int i;
    for(i=index;i<length-1;i++){
        renewItem(i,&T[i+1]);
    }
    this->length--;//删除表项,表长-1
    return true;
}

int Table::findTable(int dest){
    int i;
    for(i=0;i<this->length;i++){
        if(this->T[i].destination==dest)
            return i;
    }
    return -1;
}//在路由表中寻找destination为dest的表项,并返回位置;找不到则返回-1

int Table::campare(int index,const table* t){
    if(index==-1)
        return 2;//如果index为-1,说明表中没有该项,需要添加表项

    if((t->seq_no)>(this->T[index].seq_no)){
        if(t->metric==-1)
            return -1;
        else
            return 1;
    }//如果新来的消息中,目的主机序号seq_no比表项中对应的seq_no大,有两种可能:
    //一、metric==-1代表主机断开连接,无法到达,此时应该删除表项
    //二、该主机更新了路由信息,此时应该更新表项
    else if(t->seq_no==this->T[index].seq_no)
        if(t->metric<this->T[index].metric)
            return 1;//如果目的主机序号seq_no相等,则选择metirc代价小的路线

    return 0;
}

void Table::renewTable(const table* t){
    int index=findTable(t->destination);//找到t->dest在路由表中的位置
    int k=campare(index,t);//与表对比,得出下一步处理的类型
    switch(k)
    {   case 2:
            addTable(t);  break;
        case -1:
            deleteTable(index);  break;
        case 0:
            break;
        case 1:
            renewItem(index,t);  break;
    }
}

void Table::renewItem(int index,const table* t){
    this->T[index].destination=t->destination;
    this->T[index].metric=t->metric;
    this->T[index].nextgate=t->nextgate;
    this->T[index].nextnode=t->nextnode;
    this->T[index].seq_no=t->seq_no;
}

void Table::copytotable(int index,const dsdv_table *msg){}

void Table::copytomsg(int index,dsdv_table *msg){
    msg->setDestination(this->T[index].destination);
    msg->setMetric(this->T[index].metric);
    msg->setSeq_no(this->T[index].seq_no);
}

void Table::printTable(){
    int i=0;
    EV<<"Route table:"<<endl;
        for(i=0;i<length;i++){
            EV<<"dest:"<<T[i].destination<<" "
            <<"metric:"<<T[i].metric<<" "
            <<"nextgate:"<<T[i].nextgate<<" "
            <<"nextnode:"<<T[i].nextnode<<" "
            <<"seq_no:"<<T[i].seq_no<<endl;
        }
}

以上就是对路由表的一些操作,路由表作为路由类的成员,可方便在路由类中使用各种操作。


dsdv_table.msg:

message dsdv_table

{

int source; //源主机

int destination; //目的主机

int metric; //路径代价

int seq_no; //目的主机的序号

}

data.msg:

message data{

int source;//源地址

int destination;//目的地址

int hopCount = 0;//经过的跳数

}

 dsdv_table和data的.h 和.cpp文件不需要自己写,只要建好msg文件后build一下就可以了。(我开始看了例程还傻乎乎的自己建了两个文件,build了之后才发现多了两个文件。)

另外,data我用来模拟分组测试各节点之间传送分组,貌似cPacket类才是真的分组。


 dsdvnet.cpp:

#include <stdio.h>
#include <string.h>
#include <omnetpp.h>

using namespace omnetpp;

#include "table.h"
#include "dsdv_table_m.h"
#include "data_m.h"//记得include创建的消息类

class DsdvHost:public cSimpleModule{
private:
    Table dsdv_t;//路由表
    dsdv_table *msg_t = nullptr;//路由表项指针
    cMessage *event = nullptr;//事件event用做自消息,提醒自己按时向其他路由器发送路由表
    cMessage *data_event=nullptr;//事件data_event用作自消息
                                 //我将它用作60s后路由表稳定后,开始测试传送分组

protected:
    virtual ~DsdvHost();
    virtual void sendMessage(dsdv_table *msg,int k);//用来发送路由表
    virtual void initialize() override;//初始化,网络创建后会调用
    virtual void handleMessage(cMessage * msg) override;//接受消息,顾名思义,收到消息时调用
    virtual void forwardMessage(data *msg);//收到分组后,选择合适的gate,向前发送
    virtual data *generateMessage();//产生一个目的随机的分组
};

Define_Module(DsdvHost);

DsdvHost::~DsdvHost(){
    cancelAndDelete(event);
}

void DsdvHost::sendMessage(dsdv_table *msg,int k){
    send(msg,"gate$o",k);

}

void DsdvHost::initialize(){
    //将自己添加到表中
    table *t;
    t=new table;
    t->destination=getIndex();
    t->nextgate=-1;
    t->nextnode=getIndex();
    t->metric=0;
    t->seq_no=100;
    dsdv_t.addTable(t);
    delete t;

    //预定事件event,定时发送路由表
    event=new cMessage("event");
    scheduleAt(getIndex(),event);

    //开始由0主机发送分组
    if(getIndex()==0){
    data_event=new cMessage("send_data");
    scheduleAt(60.0,data_event);//60s时,路由表都稳定时发送
    }
}

void DsdvHost::handleMessage(cMessage * msg){
    if(strcmp("send_data", msg->getName()) == 0){
        data* d=generateMessage();
        forwardMessage(d);
    }//如果是send_data事件,产生一个分组并发送
    else if(strcmp("event", msg->getName()) == 0){
        int j,i;
        int n=gateSize("gate"),m=dsdv_t.length;
        for(i=0;i<n;i++){
            for(j=0;j<m;j++){
                msg_t=new dsdv_table("table");
                msg_t->setSource(getIndex());
                dsdv_t.copytomsg(j,msg_t);
                sendMessage(msg_t,i);
            }
         }
        scheduleAt(simTime()+10.0, event);
    }//如果是event事件,向所有邻居路由发送路由表
    else if(strcmp("table", msg->getName()) == 0){
        dsdv_table *ttmsg = check_and_cast<dsdv_table *>(msg);
        EV<<"recieved"<<endl;
        cGate *g=msg->getArrivalGate();
        EV<<"message is from:"<<ttmsg->getSource()<<"   "<<"gate["<<g->getIndex()<<"] received message"<<endl;

        table *t;
        t=new table;
        t->destination=ttmsg->getDestination();
        t->nextgate=g->getIndex();
        t->nextnode=ttmsg->getSource();
        t->metric=ttmsg->getMetric()+1;
        t->seq_no=ttmsg->getSeq_no();
        dsdv_t.renewTable(t);
        delete t;

        dsdv_t.printTable();

        delete msg;
        delete ttmsg;
    }//如果收到dsdv_table消息,更新路由表
    else{
        data *ttmsg = check_and_cast<data *>(msg);
            if (ttmsg->getDestination() == getIndex()) {
                // Message arrived.
                EV << "Message " << ttmsg << " arrived after " << ttmsg->getHopCount() << " hops.\n";
                bubble("ARRIVED, starting new one!");
                delete ttmsg;

                // Generate another one.
                EV << "Generating another message: ";
                data *newmsg = generateMessage();
                EV << newmsg << endl;
                forwardMessage(newmsg);
            }
            else {
                // We need to forward the message.
                forwardMessage(ttmsg);
            }
    }//当收到data分组时,如果目的地址是本机,收到并删除消息;否则,用forwardMessage按路由表继续转发

}

void DsdvHost::forwardMessage(data *msg){
    int index=dsdv_t.findTable(msg->getDestination());//找到对应的路由表项
    msg->setHopCount(msg->getHopCount()+1);//消息跳数+1
    send(msg,"gate$o",dsdv_t.T[index].nextgate);//发送出去
}//对分组进行转发

data * DsdvHost::generateMessage(){
    // Produce source and destination addresses.
        int src = getIndex();  // our module index
        int n = getVectorSize();  // module vector size
        int dest = intuniform(0, n-2);
        if (dest >= src)
            dest++;

        char msgname[20];
        sprintf(msgname, "tic-%d-to-%d", src, dest);

        // Create message object and set source and destination field.
        data *msg = new data(msgname);
        msg->setSource(src);
        msg->setDestination(dest);
        return msg;
}//这里直接抄tictoc例程

仿真运行:

 部分主机路由表(稳定后):

主机1:

主机3:

主机5: 

主机8: 

一些分组的发送结果:


 待实现的方面:

动态的添加,删除主机和链路。可能打算水一下作业,就不做这个了。估计就是在构造、析构或者initial、finish函数里写一些消息发送的代码吧。

注:本人菜鸟,就是应付一下作业,也没有深入学习。

OMNeT++仿真AODV(Ad hoc On-Demand Distance Vector)路由协议的步骤如下: 1. 安装OMNeT++:首先,下载OMNeT++并按照指示完成安装。 2. 下载AODV模型:从OMNeT++的官方网站或其他可靠来源下载AODV模型。 3. 导入AODV模型到OMNeT++:将下载的AODV模型导入到OMNeT++中,可以通过直接将文件复制到项目文件夹或打开OMNeT++并导入模型进行操作。 4. 配置仿真参数:在OMNeT++中,打开AODV模型并设置仿真参数,例如节点数量、通信范围、数据速率等。 5. 设计网络拓扑:在仿真环境中创建网络拓扑,设置节点位置和连通性。可以使用内置工具或自定义脚本程序进行创建。 6. 编写仿真代码:根据仿真需求,编写仿真代码以实现AODV协议的功能。 这可能包括启动节点、执行路由发现和维护过程、更新路由表、处理数据包转发等。 7. 运行仿真:保存并编译仿真代码后,使用OMNeT++运行仿真。 8. 分析仿真结果:在仿真结束后,分析仿真结果,包括路由表、数据包转发延迟、吞吐量等指标。 9. 调优和改进:根据仿真结果,调优和改进AODV协议的参数、算法等,或者尝试其他路由协议。 10. 重复步骤4-9:根据仿真需求和改进要求,重复执行步骤4到9,直到达到预期的仿真效果。 以上是在OMNeT++仿真AODV路由协议的基本步骤。在每个步骤中,需要根据具体情况进行调整和改进,以达到预期的仿真结果。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值