您的位置:首页 > 其它

对GPSR协议的理解一

2016-03-26 21:30 267 查看
GPSR协议是基于地理位置的协议。GPSR协议每个节点需要维护两个表,一个是neighborhood表,存储邻居节点;一个是sinklist表,用来存放数据接收节点,存放了本网络当中的所有节点。
下面谈一下,这两个表的建立以及维护工作。
对于邻居节点列表,节点会周期性的向其所有邻居节点广播hello分组,周期性由GPSRHelloTimer定时器控制,由以下代码实现:
void
GPSRAgent::hellotout(){
hellomsg();
hello_timer_.resched(hello_period_);
}
hellotout()函数第一条语句hellomsg()填充hello分组后,然后将hello分组广播出去;第二条语句hello_timer_.resched(hello_period_),调用hello_timei_对象(该对象是GPSRHelloTimer定时器类)。每个节点都会周期性的发送helo分组,用来告知其邻居节点。邻居节点收到hello分组后,调用recvHello()函数,具体代码如下:
void
GPSRAgent::recvHello(Packet*p){
struct hdr_cmn *cmh = HDR_CMN(p);
struct hdr_gpsr_hello *ghh =HDR_GPSR_HELLO(p);

nblist_->newNB(cmh->last_hop_,(double)ghh->x_, (double)ghh->y_);
// trace("%d recv Hello from %d", my_id_, cmh->last_hop_);
}
第三条语句nblist_->newNB(cmh->last_hop_,(double)ghh->x_, (double)ghh->y_)调用了接收到hello分组的节点的nblist_成员函数,该成员函数的类型为GPSRNeighbors *,即GPSRNeighbors类指针,进而调用函数newNB(参数分别为,发送hello分组的节点的id,发送hello分组的节点的地理位置)。GPSRNeighbors类的成员函数newNB的具体实现在Gpsr_neighbor.h中定义,在Gpsr_neighbor.cc中实现,该函数的作用是如果邻居列表中有该节点则更新该节点的位置信息,如果不存在该节点那么在neighbor列表最后tail_增加一个gpsr_neighbor结构体(用于存放该邻居节点的信息)。
对于节点创建与维护的sinklist列表,是由query分组以及GPSRQueryTimer定时器共同实现的。节点几乎存放了本网络中所有的节点的地址,这样它在有发送数据的意愿是,才能通过getLocbyID()函数查询到该目的节点所处的地理位置,然后才能填充数据包,通过贪婪转发以及边界转发传送数据包到达目的地址。周期性由GPSRQueryTimer定时器定时触发,代码如下:

void
GPSRAgent::startSink(doublegp){
query_period_ = gp; //设置query周期
startSink(); //调用startSink()函数
}
void
GPSRAgent::startSink(){
if(sink_list_->new_sink(my_id_, my_x_,my_y_,
my_id_, 0,query_counter_))
//new_sink()函数在发送query分组以及接收query分组时都会调用,用于更新节点信息。
querytout();
}
void
GPSRAgent::querytout(){
query(my_id_);
query_counter_++;
query_timer_.resched(query_period_);
}
上面这个querytout()函数,第一行语句query(my_id_)用于填充自己的节点信息(主要是地理位置信息)到query分组,在填充query分组时,ip->sddr()填充的是最原始发送query分组的节点ip。网络中的各个节点都需要定时向网络中的其他节点告知自己的地理位置,就是通过节点自己发送query分组实现的。第三条语句query_timer_.resched(query_period_),调用query_timer_成员变量(该成员变量是GPSRQueryTimer*类型,即GPSRQueryTimer类指针)的resched()函数重新设置GPSRQueryTimer定时器的超时时间。既然节点自己会定期通知其他节点自己的地理位置,那么就会有网络中的其他节点接收该query分组,节点是通过recvQuery()函数来接受到达自己的query分组的。RecvQuery()函数的具体代码如下:
void
GPSRAgent::recvQuery(Packet*p){
struct hdr_cmn *cmh = HDR_CMN(p);
struct hdr_ip *iph = HDR_IP(p);
struct hdr_gpsr_query *gqh =HDR_GPSR_QUERY(p);

if(sink_list_->new_sink(iph->saddr(),gqh->x_, gqh->y_,
cmh->last_hop_, 1+gqh->hops_,gqh->seqno_))
query(iph->saddr());
// trace("%d recv Query from %d ", my_id_, iph->saddr());
}
节点首先调用new_sink()函数(参数分别为,最初生成该query分组的id,地理位置x,y,该query分组的上一跳,到该节点的跳数,以及该query分组的序列号),该函数首先检查本节点的sinklist_列表中该id代表的节点entry信息是否更新,检查地理位置信息是否改变,以及检查该query分组的新旧程度(通过比对接收到的entry与本节点原始的关于该id的entry的seqno_,越大表明该query越新,还有比对跳数),如果接收到的id的entry信息没有更新,那么new_sink()函数返回false,recvQuery函数直接返回;如果接收到的id的entry信息改变,那么更新在sinklist_表中关于该id的entry信息,返回true,接着执行query(iph->saddr())语句,该语句继续继续发送最原始的query分组信息,知道该网络中所有节点都已知晓最初产生query分组的节点的地理信息。
以上就是GPSR协议中关于节点的邻居表以及接受数据表的建立与维护情况。
以上内容是自己阅读代码的理解,如果出处,请谅解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: