Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1311075
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3936
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: 嵌入式

2012-07-11 22:16:20

摘要:

    本文讲述Rime协议栈单跳单播的连接建立过程,即rucb_open --> runicast_open --> stunicast_open --> unicast_open --> broadcast_open --> abc_open --> channel_open。


一、概述

1.1 讨论范围

    使用Rime协议栈进行通信,需要先建立连接。Rime协议栈提供单跳单播、单跳广播、多跳三种功能,本文仅介绍单跳单播(Single-hop unicast)连接建立过程,如下图红色箭头所示:

图1 Rime协议栈系统框图

    图1蓝色下划线suc、stuc是两篇不同论文的名称,事实上是同一个意思。因源代码用的也是stuc,故在以后讨论使用stuc。关于图1各名词解释,详见博文《Contiki学习笔记:Rime协议栈概述及学习资料》。

1.2 连接建立概述

Rime是层次型协议栈,整个连接过程是通过上层调用下层服务来完成的,具体如下:

    rucb_open --> runicast_open --> stunicast_open --> unicast_open --> broadcast_open --> abc_open --> channel_open

1.3 几点说明

    使用Rime协议栈进行通信之前,需要建立连接,也就需要保存该连接一些信息(如发送者、接收者),Rime协议栈用一系列结构体保存这些链接状态信息。Rime每一层都有相应的连接结构体(以_conn结尾),上层嵌套下层,如下:

    rucb_conn --> runicast_conn --> stunicast_conn --> unicast_conn --> broadcast_conn --> abc_conn

    每个连接结构体都有相应的回调结构体(以_callbacks后缀结尾),该结构体的成员变量实为发送、接收函数指针。当接收到一个数据报,会调用该结构体相应的函数。回调结构体层次如下:

    rucb_callbacks --> runicast_callbacks --> stunicast_callbacks --> unicast_callbacks --> broadcast_callbacks --> abc_callbacks

    综上,连接建立_open、连接结构体_conn、回调结构体_callbacks间的关系如下图:

open、coon、callbacks对应关系源文件 open、coon、callbacks对应关系.rar   

图2 open、coon、callbacks对应关系

    为了便于叙述,将连接结构体_conn、回调结构体_callbacks分别单列成文,阅读本文后续内容,请结合如下博文:

博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之结构体rucb_conn

博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks

    事实上,整个连接过程,就是设置相应的连接结构体成员变量,所以建立先阅读下博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之结构体rucb_conn

1.4 一个实例

文件contiki/examples/rime/example-rucb.c给出一个使用rucb实例,建立连接部分源代码如下:

  1. static struct rucb_conn rucb;
  2. const static struct rucb_callbacks rucb_call =
  3. {
  4.   write_chunk,
  5.   read_chunk,
  6.   NULL
  7. };
  8. rucb_open(&rucb, 137, &rucb_call);

    定义连接结构体rucb,实现回调结构体中的函数并定义回调结构体rucb_call,指定一个通道号调用rucb_open建立连接。

二、rucb_open

rucb是块传输(Bulk transfer)层[1],可以理解成传输层,rucb_open源代码如下:

  1. void rucb_open(struct rucb_conn *c, uint16_t channel, const struct rucb_callbacks *u)
  2. {
  3.   rimeaddr_copy(&c->sender, &rimeaddr_null);
  4.   runicast_open(&c->c, channel, &ruc);
  5.   c->u = u;
  6.   c->last_seqno = - 1;
  7. }

rimeaddr_copy

    将Rime地址rimeaddr_null拷贝到sender,即将sender设为0.0(当Rime地址长度为2)。关于Rime地址rimeaddr_t及函数rimeaddr_copy相关介绍见博文《Contiki学习笔记:Rime协议栈之Rime地址rimeaddr_t》。

runicast_open

    见第三部分。

c->u = u

    结构体rucb_callbacks有3个函数指针成员变量写数据块write_chunk、读数据块read_chunk、超时timedout,这三个函数由用户自己实现,建立连接时作为参数传给rucb_open(见1.4例子)。

c->last_seqno = -1

    一次数据发送多个片段的最后一个序列号,当接收端接收到数据时,判断其序列号是否等于最后一个序列号,若等于则不接收(即接收到最后一个数据块,停止接收)。last_seqno 初始化为-1。

三、runicast_open

    ruc是可靠通信的另一层,该层主要实现确认和序列功能(acknowledgments and sequencing)[1],runicast_open源代码如下:

  1. //static const struct runicast_callbacks ruc = {recv, acked, timedout};
  2. //runicast_open(&c->c, channel, &ruc);

  3. void runicast_open(struct runicast_conn *c, uint16_t channel, const struct runicast_callbacks *u)
  4. {
  5.   stunicast_open(&c->c, channel, &runicast);
  6.   channel_set_attributes(channel, attributes);
  7.   c->u = u;
  8.   c->is_tx = 0;
  9.   c->rxmit = 0;
  10.   c->sndnxt = 0;
  11. }

stunicast_open

    见第四部分。

channel_set_attributes

    设置通道channel属性,关于结构体通道channel及函数channel_set_attributes介绍见博文《Contiki学习笔记:Rime协议栈通道channel》。这里的参数attributes是数组指针,具体展开比较繁琐,遂单独成文《Contiki学习笔记:Rime协议栈Rime协议栈单跳单播头部》。

c->u = u

    结构体runicast_callbacks有3个函数指针成员变量接收recv、发送sent、超时timedout,分别映射到接收recv、确认acked、超时timedout函数(在contiki/core/net/rime/rucb.c实现),详情见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks》。

is_tx、rxmit、max_rxmit

    is_tx、rxmit、max_rxmit是结构体runicast_conn的成员变量,均初始化为0,关于is_tx、rxmit、max_rxmit介绍见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之结构体rucb_conn》。

四、stunicast_open

    stuc是可靠通信的另一层,该层在给定的时间间隔不断地重发数据包,直到上层让其停止。为了防止无限重发,需要指定最大重发次数(maximum retransmission number)[1],stunicast_open源代码如下:

  1. //static const struct stunicast_callbacks runicast = {recv_from_stunicast,sent_by_stunicast};
  2. //stunicast_open(&c->c, channel, &runicast);

  3. void stunicast_open(struct stunicast_conn *c, uint16_t channel, const struct stunicast_callbacks *u)
  4. {
  5.   unicast_open(&c->c, channel, &stunicast);
  6.   c->u = u;
  7. }

unicast_open

    见本文第五部分。

c->u = u

    结构体stunicast_callbacks有2个函数指针成员变量接收recv、发送sent,分别映射到接收recv_from_stunicast、发送sent_by_stunicast函数(在contiki/core/net/rime/runicast.c实现),详情见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks》。

五、unicast_open

    uc(unicast abstraction)将上层的数据包添加一个接收者头部(adds a receiver header field)[1],unicast_open源代码如下:

  1. //static const struct unicast_callbacks stunicast = {recv_from_uc, sent_by_uc};
  2. //unicast_open(&c->c, channel, &stunicast);

  3. void unicast_open(struct unicast_conn *c, uint16_t channel, const struct unicast_callbacks *u)
  4. {
  5.   broadcast_open(&c->c, channel, &uc);
  6.   c->u = u;
  7.   channel_set_attributes(channel, attributes);
  8. }

broadcast_open

    见本文第六部分。 

c->u = u

    结构体unicast_callbacks有2个函数指针成员变量接收recv、发送sent,分别映射到接收recv_from_uc、发送sent_by_uc函数(在contiki/core/net/rime/stunicast.c实现),详情见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks》。

channel_set_attributes

    设置通道channel属性,关于结构体通道channel及函数channel_set_attributes介绍见博文《Contiki学习笔记:Rime协议栈通道channel》。这里的参数attributes是数组指针,具体展开比较繁琐,遂单独成文《Contiki学习笔记:Rime协议栈Rime协议栈单跳单播头部》。

六、broadcast_open

    ibc(identified sender best-effort broadcast)将上层的数据包添加一个发送者身份(sender identity)头部[1],broadcast_open源代码如下:

  1. //static const struct broadcast_callbacks uc = {recv_from_broadcast, sent_by_broadcast};
  2. //broadcast_open(&c->c, channel, &uc);

  3. void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u)
  4. {
  5.   abc_open(&c->c, channel, &broadcast);
  6.   c->u = u;
  7.   channel_set_attributes(channel, attributes);
  8. }

abc_open

    见本文第七部分。 

c->u = u

    结构体broadcast_callbacks有2个函数指针成员变量接收recv、发送sent,分别映射到接收recv_from_broadcast、发送sent_by_broadcast函数(在contiki/core/net/rime/unicast.c实现),详情见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks》。 

channel_set_attributes

    设置通道channel属性,关于结构体通道channel及函数channel_set_attributes介绍见博文《Contiki学习笔记:Rime协议栈通道channel》。这里的参数attributes是数组指针,具体展开比较繁琐,遂单独成文《Contiki学习笔记:Rime协议栈Rime协议栈单跳单播头部》。

七、abc_open

    abc(anonymous broadcast,匿名广播)将数据包通过无线射频驱动(radio driver)发出去,接收来自无线射频驱动所有的包并交给上层[1],abc_open源码如下:

  1. //static const struct abc_callbacks broadcast = {recv_from_abc, sent_by_abc};
  2. //abc_open(&c->c, channel, &broadcast);

  3. void abc_open(struct abc_conn *c, uint16_t channelno, const struct abc_callbacks *callbacks)
  4. {
  5.   channel_open(&c->channel, channelno);
  6.   c->u = callbacks;
  7.   channel_set_attributes(channelno, attributes);
  8. }

channel_open

    见本文第八部分。 

c->u = callbacks

    结构体abc_callbacks有2个函数指针成员变量接收recv、发送sent,分别映射到接收recv_from_abc、发送sent_by_abc函数(在contiki/core/net/rime/broadcast.c实现),详情见博文《Contiki学习笔记:Rime协议栈单跳单播建立连接之callbacks》。

channel_set_attributes

    设置通道channel属性,关于结构体通道channel及函数channel_set_attributes介绍见博文《Contiki学习笔记:Rime协议栈通道channel》。这里的参数attributes是数组指针,具体展开比较繁琐,遂单独成文《Contiki学习笔记:Rime协议栈Rime协议栈单跳单播头部》。

八、channel_open

    channel_open用于打开一个通道,实际上是设置通道号并将通道c加到channel链表中,详情见博文《Contiki学习笔记:Rime协议栈通道channel》,channel_open源代码如下:

  1. //channel_open(&c->channel, channelno);

  2. void channel_open(struct channel *c, uint16_t channelno)
  3. {
  4.   c->channelno = channelno;
  5.   list_add(channel_list, c);
  6. }


至此,单跳单播连接整个过程介绍完毕:-)


参考资料:

[1] 博文《Contiki学习笔记:Rime协议栈概述及学习资料

[2] Adam Dunkels,Fredrik Osterlind,Zhitao He. An Adaptive Communication Architecture for Wireless Sensor Networks[J]

阅读(3202) | 评论(0) | 转发(5) |
给主人留下些什么吧!~~