Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导
Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导
Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导
之前为大家介绍了一下Veins的入门知识,现在教大家怎么在Veins的基础上实现多跳路由,其实基本掌握了Veins后实现思路并不难理解,实现一个简单的算法也不难,难的是提出一个更优的路由协议,调试出更好的结果,本文给大家介绍个简单的例子:通过广播RREQ(一些名词我就不解释了)寻找目的节点的位置,目的节点收到RREQ后单播返回RREP给源节点,源节点根据RREP内记录的目的节点位置信息选择距离目的节点最近的邻居节点作为下一跳节点并将数据包传给此节点,之后的每一跳节点也都采用这种转发逻辑选择下一跳节点,直到数据包传至目的节点。
主要是指导,辅助贴几张源码截图,更多的细节都是搞研究的自己摸索吧。( ˘▽˘)っ加油宝宝们,我也是这么过来的。最后如果对大家研究有帮助、有启发,大家发论文有心的引一下我的博客,嫌麻烦的也没关系。又啰里啰嗦了一大堆~
必要的message类实现
路由就是用来传输message的,各种各样的message,既有我们要传的数据帧,也有维持正常传输所需的各种辅助帧,比如RREQ、RREP、RERR、Beacon等等。怎么实现它们呢,其实并不难,我们到veins/src/veins/modules/messages下面就可以发现一些veins内置的message类,把它们copy一下(包括.h,.cc,.msg),然后改一下类名(直接用查找替换,不用管它是怎么实现的),然后在对应的.h后缀名文件内的如下图位置添上自己需要这个message携带的各种数据格式(截图内的源码为草稿,为了赶时间狂写狂改的,各种代码冗余、命名不规范等问题,各位编程大神不要见笑),
补充一下:在对应的.msg文件里面也要加上对应的变量

之后进入如下图所示的文件夹内打开终端,

依次输入如下命令进行编译,

OMNeT++会自动为你在新加的message类文件内添加好对应数据的设置和读取函数,比如

至此message类就实现了,后面写路由协议的时候把相应的类导进来,然后就可以直接调用了,比如RREQ传到目的节点,目的节点生成RREP后将自己的位置写入其中,使用RREQ的getAlongNodeID函数(仔细看上面的图)得到沿路节点的ID(这就需要每一跳节点接收到RREQ后将自己的ID写入RREQ携带的alongNodeID[100]数组的对应位置),写入RREP,然后单播转发RREP,每一跳节点都从alongNodeID[100]查找上一跳节点ID并传给它(要查找上一跳还需要hopNumber这一计数变量辅助),最终单播返回源节点,是不是很简单~
从下面开始是在veins/src/veins/modules/application/ieee80211p文件夹内进行操作
还是按上一节的操作,将BaseWaveApplLayer对应的.h .cc .ned文件copy一下改成自己的类名,以此为基础实现自己的路由逻辑,以下设为MultihopBaseWaveApplLayer。
Beacon
OMNeT++是分布式实现网络仿真的,因此我们无法从系统的层面(也就是上帝视角)对仿真过程进行操纵,这也就是为什么要用广播RREQ的方式找到目的节点,而无法直接将目的节点的位置坐标告知源节点指导其数据转发,当然这也是有好处的,这使得我们的仿真更加贴合实际,将来工程化的时候这些函数拿出来直接就能用了。
既然无法从上帝视角进行操作,那么每个节点是怎么确定周围有多少邻居节点以及它们的信息的呢?
通过Beacon,也就是每隔一定时间(为了减少数据包碰撞,可以采用变时长,这是一个研究方向)广播Beacon帧,里面携带当前节点的位置、速度、所处道路ID等信息(Beacon携带的信息按上一节介绍的也可以自己设计)。然后周围节点接收到Beacon帧后将相关信息加入自己的邻居节点信息表内(在MultihopBaseWaveApplLayer内用struct结构自己设计一个,然后用作MultihopBaseWaveApplLayer的成员变量)。
Beacon是定时的,怎么实现这种定时操作呢?
如图所示,在initialize(初始化)的时候就通过scheduleAt给自己定时发送了sendBeaconEvt消息。另外两个nextRoutEvt和routeSearchCheckEvt是我用来定时发送下一个数据包和检查之前的RREQ广播出去有没有收到RREP的,如果没有的话再重新路由探索。(反正各种情况都要考虑到,细讲的话可以开门课了,你们自己实现吧)。

MultihopBaseWaveApplLayer中用下面这个函数handleSelfMsg接收各种自己发给自己的消息,实现定时自操作,接收到消息后再使用scheduleAt定时给自己发消息,就能实现循环定时操作了。

MultihopBaseWaveApplLayer自己接收到给自己发的sendBeaconEvt后生成Beacon并使用sendDown函数发往下一层MAC层(细读源码,我也不细讲Veins的结构了),之后MAC层一顿操作,什么信道切换、什么EDCA机制、什么随机退避,之后通过物理层将Beacon帧广播出去。
邻居节点的MultihopBaseWaveApplLayer怎么接收Beacon等其他各种数据帧的呢?
通过如下图所示函数handleLowerMsg,可以接收各类从MAC层传上来的数据帧,至于物理层、MAC层怎么操作的不用管,我们只要得到这个数据帧就行,然后通过onBSM函数收集邻居节点的信息存到本地邻居节点信息集内。那么onBSM函数里面写了些什么呢?这就是秘密了~

路由探索
路由探索就是之间讲的广播RREQ寻找目的节点,目的节点收到RREQ单播返回RREP给源节点的过程。
思路很简单,初始化的时候定个时某个时刻随机生成个目的节点ID(不太好,最后自己先用默认的例子跑一遍自己生成的交通流,看看有哪些节点,自己选个合适的目的节点),在handleSelfMsg对应位置生成RRRQ然后sendDown,采用广播的形式,每个节点收到RREQ后(handleLowerMsg函数)看看自己是不是目的节点,如果不是则再次广播出去(这种广播方式造成广播风暴,引发大量的数据帧碰撞,如何优化广播机制也是个研究方向),直到目的节点收到RREQ。每个节点接收到RREQ后都将自己的ID写入其中,目的节点收到RREQ就可以根据这个单播返回RREP。
RREP的单播返回是怎么实现的呢?
数据都是广播出去的,只要处于信号覆盖范围就能收到,但是如果只有数据帧内设好的下一跳节点接收到此数据帧才进行后续操作,其他节点收到数据后不进行处理则可实现单播,这样做的好处是每个接收到数据帧的节点不必都广播,减轻了数据碰撞的程度。
RREP根据RREQ记录的沿路节点ID(目的节点从RREQ中读取并在生成RREP时写入RREP)设置下一跳节点ID这一类变量,即可实现前述单播操作。
路由传输
确定好目的节点位置后,即进行正式的数据传输,采用前述单播方式传输数据。通过对比邻居节点集各邻居节点的位置与目的节点的位置,选取距离目的节点最近的邻居节点作为下一跳节点。(如果没有邻居节点比当前节点距离目的节点更近呢?此时采取右手转发,有基础的可能发现了,我讲的就是GPSR路由协议( ̄︶ ̄)↗)同样的也是在每个节点的MultihopBaseWaveApplLayer的handleLowerMsg函数接收到相应类型数据帧时进行操作。大家是不是开始理会到了OMNeT++分布式操作的含义了~
剩下的路由错误、路由恢复就不说了,都是细节。
最后实现出来的效果就是下面这样了,粉色是RREQ,绿色代表正式的数据帧,黄色代表目的节点接收到数据帧后返回的数据确认帧(ACK),小圆代表中转节点,大圆代表目的节点。

Veins(车载通信仿真框架)入门教程(三)——多跳路由实现指导的更多相关文章
- Veins(车载通信仿真框架)入门教程(四)——调试及记录结果
Veins(车载通信仿真框架)入门教程(四)——调试及记录结果 在Veins入门教程(三)最后的动图中(如下图)可以看到大大小小的光圈,这个怎么实现的呢? 很简单,以收到RTS消息为例,通过finHo ...
- Veins(车载通信仿真框架)入门教程(二)——调用第三方库
Veins(车载通信仿真框架)入门教程(二)——调用第三方库 在借助Veins进行自己的研究时我们经常需要实现一些比较复杂的功能,有时就需要借助第三方库的帮助. 博主的研究需要使用神经网络,但是自己编 ...
- Veins(车载通信仿真框架)入门教程
Veins入门教程——教你如何下手研究 目录 Veins入门教程——教你如何下手研究 目录 废话少说! 讲解omnetpp.ini!(挑关键的) 讲解RSUExampleScnario.ned! 注意 ...
- 无废话ExtJs 入门教程三[窗体:Window组件]
无废话ExtJs 入门教程三[窗体:Window组件] extjs技术交流,欢迎加群(201926085) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3 ...
- Go-Micro框架入门教程(一)---框架结构
Go语言微服务系列文章,使用golang实现微服务,这里选用的是go-micro框架,本文主要是对该框架的一个架构简单介绍. 1. 概述 go-micro是go语言下的一个很好的微服务框架. 1.服务 ...
- CodeIgniter框架入门教程——第一课 Hello World!
本文转载自:http://www.softeng.cn/?p=45 今天开始,我将在这里连载由我自己编写的<CodeIgniter框架入门教程>,首先,这篇教程的读着应该是有PHP基础的编 ...
- Java - Struts框架教程 Hibernate框架教程 Spring框架入门教程(新版) sping mvc spring boot spring cloud Mybatis
https://www.zhihu.com/question/21142149 http://how2j.cn/k/hibernate/hibernate-tutorial/31.html?tid=6 ...
- PySide——Python图形化界面入门教程(三)
PySide——Python图形化界面入门教程(三) ——使用内建新号和槽 ——Using Built-In Signals and Slots 上一个教程中,我们学习了如何创建和建立交互widget ...
- Elasticsearch入门教程(三):Elasticsearch索引&映射
原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...
随机推荐
- 在网页中打印一个99乘法表--JavaScript描述
99乘法表使用for循环,在很多公司的面试中常会要求面试者手写这个算法,算是比较经典的for循环的应用 <!DOCTYPE html><html lang="en" ...
- .NET进阶篇-丑话先说,Flag先立
作为开发者,工作了几年,也总觉得技术栈和刚毕业区别不大,用的技术还都是N年前的,每每看到新东西,也只心里哇塞惊叹一下,然后就回归于忙碌.怪自己的技术池太浅,热门的令人称奇的技术也都是在其他巨人的肩膀上 ...
- 前沿科技-混合现实(MR)远程协作辅助工具:微缩虚拟形象Mini-Me
今天分享一篇在刚刚结束的CHI’2018上发表的full paper.该文章由来自澳洲University of South Australia的Piumsomboon等人和来自新西兰Universi ...
- Java基础学习笔记(五) - 常用的API
API介绍 概念:API 即应用编程程序接口.Java API是JDK中提供给我们使用的类说明文档,这些类将底层的代码实现封装.无需关心这些类是如何实现,只需要学习如何使用. 使用:通过API找到需要 ...
- Linux简单检查服务运行脚本
脚本内容如下: 此脚本含义:检查服务是否运行,在运行则记录日志,不在运行则记录日志并将服务启动 #!/bin/bash svrnm="tomcat" //设置服务名称time=`d ...
- Unknown column 'user_id' in 'where clause'
mapper位置报错Unknown column 'user_id' in 'where clause' 可能是数据库中的字段user_id包含空格
- 视频转换器 Wondershare Video Converter Ultimate v11.5.1 中文便携版
Wondershare Video Converter Ultimate 是万兴公司出品的一款多功能音视频转换.DVD 刻录软件.视频下载软件.有了它,您可以随时随地观看.下载.编辑.转换.刻录视频, ...
- Spring5源码解析5-ConfigurationClassPostProcessor (上)
接上回,我们讲到了refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory)方法主要在执行BeanFactoryPostProcessor和其子 ...
- 洛谷 P1717 钓鱼
题目描述 话说发源于小朋友精心设计的游戏被电脑组的童鞋们藐杀之后非常不爽,为了表示安慰和鼓励,VIP999决定请他吃一次“年年大丰收”,为了表示诚意,他还决定亲自去钓鱼,但是,因为还要准备2013NO ...
- 《深入理解Java虚拟机》-----第13章 线程安全与锁优化
概述 在软件业发展的初期,程序编写都是以算法为核心的,程序员会把数据和过程分别作为独立的部分来考虑,数据代表问题空间中的客体,程序代码则用于处理这些数据,这种思维方式直接站在计算机的角度去抽象问题和解 ...