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版权协议,转载请附上原文出处链接和本声明. 本文 ...
随机推荐
- 用 C# 来守护 Python 进程
背景 目前我主要负责的一个项目是一个 C/S 架构的客户端开发,前端主要是通过 WPF 相关技术来实现,后端是通过 Python 来实现,前后端的数据通信则是通过 MQ 的方式来进行处理.由于 Pyt ...
- 使用Fedora8 iso开发环境开发gtk3跨Linux多版本桌面应用
原文: https://bbs.otherhill.com/index.php/topic/show/82 gtk3 demo在/usr/local/gtk3demo 目录下 cd /usr/loca ...
- JavaScript学习记录
js整理笔记 1.数据类型 2.基本语法 3.js运算符 4.条件语句 5.类型转换 6.函数 7.预编译 8.作用域 9.闭包 10.对象创建方法 11.this 12.dom操作 13.事件 14 ...
- 分布式session共享机制分析
使用配置: 1.在pom文件中引入spring-session的jar包 <!--springsession--><dependency><groupId>org. ...
- 死磕 java同步系列之mysql分布式锁
问题 (1)什么是分布式锁? (2)为什么需要分布式锁? (3)mysql如何实现分布式锁? (4)mysql分布式锁的优点和缺点? 简介 随着并发量的不断增加,单机的服务迟早要向多节点或者微服务进化 ...
- Linux 文件复制命令cp
文件复制命令cp 命令格式:cp [-adfilprsu] 源文件(source) 目标文件(destination) cp [option] source1 source2 source3 ... ...
- Linux系列之yum安装
yum是Linux系统的安装必备神器,简直不要太方便.但是新系统一般是不自带yum工具的,所以需要手动安装一下. 环境:centos7 新建一个目录用来保存yum安装包 mkdir install 进 ...
- TF-IDF算法——原理及实现
TF-IDF算法是一种用于信息检索与数据挖掘的常用加权技术.TF的意思是词频(Term - frequency),IDF的意思是逆向文件频率(inverse Document frequency). ...
- 计算机视觉(二)-opencv之createTrackbar()详解
摘要: 我学习openCV3看的是<学习openCV3>这本书,很厚的一本,不知道是不是因为自己看的还不是很多,个人觉得里面的有些重要函数讲的不是很详细,比如createTrackbar( ...
- Nebula 架构剖析系列(零)图数据库的整体架构设计
Nebula Graph 是一个高性能的分布式开源图数据库,本文为大家介绍 Nebula Graph 的整体架构. 一个完整的 Nebula 部署集群包含三个服务,即 Query Service,S ...