rucb是单跳单播的最顶层,将数据以块为单位进行传输(Bulk transfer)。

  ruc,Reliable communication,保证可靠通信,主要实现确认和序列功能。

  suc,Stubborn transmission,可靠通信的另一层。suc这一层在给定的时间间隔不断地重复发送数据包,直到上层让其停止。为防止无限重发,需要指定最大重发次数。

  uc,unicast abstraction,将上层的数据包添加一个接收者头部。

  ibc,identified sender best-effort broadcast,将上层的数据包添加一个发送者身份头部

  abc,anonymous broadcast,匿名广播。即将数据包通过无线射频驱动(radio driver)发出去,接收来自无线射频驱动所有的包并交给上层。

建立连接

  建立连接的实质是保存该连接一些信息(如发送者、接收者),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间的关系如下图:

  

1>连接结构体

  建立连接,实质是初始化结构体rucb_conn各个成员变量,结构体rucb_conn定义如下:

struct rucb_conn {
struct runicast_conn c;
const struct rucb_callbacks *u;
rimeaddr_t receiver, sender;
uint16_t chunk;
uint8_t last_seqno;
int last_size;
};

c

  下一层连接结构体

u

  结构体rucb_callbacks有3个函数指针成员变量,写数据块write_chunk、读数据块read_chunk、超时timeout,需要用户自己实现。

receiver、sender

  用于标识接收者和发送者。receiver是指目的节点的接收地址

chunk

  数据块数目

last_seqno

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

数据发送

  Rime协议栈建立连接后,就可以通信了(发送、接收数据),下面介绍单跳单播的发送数据情形。

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

  rucb_send --> runicast_send --> stunicast_send_stubborn --> unicast_send --> broadcast_send --> abc_send -->rime_output -->NETSTACK_MAC.send

  rucb是块传输层,可以理解成传输层,数据发送函数rucb_send的源代码如下:

int rucb_send(struct rucb_conn *c, const rimeaddr_t *receiver)
{
c->chunk = ;
read_data(c);
rimeaddr_copy(&c->receiver, receiver);
rimeaddr_copy(&c->sender, &rimeaddr_node_addr);
runicast_send(&c->c, receiver, MAX_TRANSMISSIONS);
return ;
}

  c->chunk将数据块数目初始化为0,read_data进行一些Rime缓冲区初始化相关工作。rimeaddr_copy函数设置接收者receiver和发送者sender的Rime地址,rimeaddr_node_addr用于标识本节点的Rime地址。接下来调用下一层的发送函数runicast_send完成发送。

数据接收

  Rime协议栈建立连接后,就可以调用数据接收函数recv来接收数据,整个接收数据过程是通过上层调用下层服务来完成的,具体如下:

  recv --> recv_from_stunicast --> recv_from_uc --> recv_from_broadcast -->recv_from_abc

  函数recv首先判断该数据包是不是最后一个序列(数据包被拆分的情况下),若不是,将收到的数据写入物理存储介质。recv函数流程图如下:

 

 static void recv(struct runicast_conn *ruc, const rimeaddr_t *from, uint8_t seqno)
{
struct rucb_conn *c = (struct rucb_conn *)ruc; PRINTF("%d.%d: rucb: recv from %d.%d len %d\n",
rimeaddr_node_addr.u8[],rimeaddr_node_addr.u8[],
from->u8[], from->u8[], packetbuf_totlen()); if(seqno == c->last_seqno) {
return;
}
c->last_seqno = seqno; if(rimeaddr_cmp(&c->sender, &rimeaddr_null)) {
rimeaddr_copy(&c->sender, from);
c->u->write_chunk(c, , RUCB_FLAG_NEWFILE, packetbuf_dataptr(), );
c->chunk = ;
} if(rimeaddr_cmp(&c->sender, from)) {
int datalen = packetbuf_datalen(); if(datalen < RUCB_DATASIZE) {
PRINTF("%d.%d: get %d bytes, file complete\n",
rimeaddr_node_addr.u8[], rimeaddr_node_addr.u8[],
datalen);
c->u->write_chunk(c, c->chunk * RUCB_DATASIZE,
RUCB_FLAG_LASTCHUNK, packetbuf_dataptr(), datalen);
} else {
c->u->write_chunk(c, c->chunk * RUCB_DATASIZE,
RUCB_FLAG_NONE, packetbuf_dataptr(), datalen);
}
c->chunk++;
} if(packetbuf_datalen() < RUCB_DATASIZE) {
rimeaddr_copy(&c->sender, &rimeaddr_null);
}
}

  函数recv首先判断接收到的包是不是最后一个序列(数据包太大时,需要拆分),如果是最后一个就返回(用最后序列号标识包传递完毕)。若不是最后一个序列,意味着还有数据要接收。接着判断发送者地址是否为空,若是,说明节点未曾接收到该包的任何序列,则建立文件以存放数据。确保发送地址无误之后,若块小于块的最大值(RUCB_DATASIZE),即这是数据包的最后的一块,写入最后一块,否则正常写入这块的数据。把块的数目累加,接着判断这块是否是最后一块(最后一块意味着数据包传输完毕),若是则将发送者地址设为空,否则返回。

释放连接

  数据通信完毕之后,需要释放连接,以供其他进程是哟个。关闭连接实质上是将相应的连接结构体从连接表中删除。整个调用过程如下:

  rucb_close --> runicast_close --> stunicast_close --> unicast_close --> broadcast_close --> abc_close --> channel_close -->list_remove

contiki-rime-单跳单播的更多相关文章

  1. 表单跳转到Struts2

    在使用表单跳转到Struts2时,路径一直不正确. login.html如下: <form action="login.do" method=post> 账号:< ...

  2. 原生js阻止表单跳转

    /* W3C浏览器下的 */ var forms = document.getElementById("from") forms.addEventListener('submit' ...

  3. H3C 路由器单跳操作

  4. [Contiki系列论文之2]WSN的自适应通信架构

    说明:本系列文章翻译自Contiki之父Adam Dunkels经典论文,版权归原作者全部. Contiki是由Adam Dunkels及其团队开发的系统.研读其论文是对深入理解Contiki系统的最 ...

  5. Djangoform表单Ajax控制跳转

    需求: 1:在登陆页面输入账号密码后,ajax异步提交数据给后端验证. 2:验证通过后,后端指定跳转页面,并把页面封装进返回的Json数据中,由ajax控制from表单跳转到目标页面 一:登陆页面HT ...

  6. AutoIt 脚本小试——刷网易云音乐歌单

    AutoIt 确实是个很强大的脚本工具. 如果早知道有这个,当初是怎么都不会去学易语言的  (๑•̀ω•́๑) 这是个简单脚本 = ๛ก(ー̀ωー́ก) 用来增加歌单播放次数和个人的听歌量. 原理不过 ...

  7. Servlet3.0 jsp跳转到Servlet 出现404错误的路径设置方法

    最近又遇到了这种问题,百度了好久,发现有人说要在action的路径里面写Servlet文件的绝对路径,比如说,单独打开servlet的地址为http://localhost:8080/TomcatTe ...

  8. ajax跳转到新的jsp页面

    ajax可以实现局部刷新页面,即在不刷新整个页面的情况下更新页面的局部信息. 项目中遇到一个问题:在用户列表也,当点击某个按钮时需要去查询用户的信息,查询成功跳转到用户详情界面:查询失败,则在原页面弹 ...

  9. layui---表单验证

    使用layui,使用它的表单验证也是比不可少的,下面就来总结下: <!-- 不用form 用div也可以 --> <form class="layui-form" ...

随机推荐

  1. 夺命雷公狗-----React---19--表单的值的修改

    少了1个e,在代码部分补回,否则会报错 <!DOCTYPE> <html> <head> <meta charset="utf-8"> ...

  2. 【KeyCode 键码】

    Key codes returned by Event.keyCode. These map directly to a physical key on the keyboard. KeyCode是由 ...

  3. Linux下make与makefile

    make 用来解析 makefile 文件 make 的选项:-d   显示调试信息-f 文件  默认是从 makefile 或 Makefile 中读取依赖信息,用该选项可更改文件-h   显示所有 ...

  4. 分布式入门之1:Lease机制

      引子: 分布式系统中,如何确认一个节点是否工作正常?   如果有3副本A.B.C,并通过中心结点M来管理.其中A为主副本. 未接触过分布式的直观的处理方法是在每个副本与中心节点M中维护一个心跳,期 ...

  5. YbSoftwareFactory 代码生成插件【十九】:实体类配合数据库表字段进行属性扩展的小技巧

    实体类通常需要和数据库表进行了ORM映射,当你需要添加新的属性时,往往同时也需要在数据库中添加相应的字段并配置好映射关系,同时可能还需对数据访问组件进行重新编译和部署才能有效.而当你开始设计一个通用数 ...

  6. Mono.Ceil 无法保存Silverlight 程序集

    一句话: 处理Silverlight程序集之前, 须先移除强名称(StrongNameRemoveHelper), 之后Reflexil 即可一如预期的正常工作.

  7. 读书笔记 --TCP :传输控制协议(二)

    TCP建立连接 请求端(客户端)发送一个SYN指明客户端打算连接的服务器端口号,以及初始序列号. 服务端发回包含服务器的初始序号的SYN报文段作为应答.同时,将确认序号设置为客户的ISN加1以对客户的 ...

  8. C#调用RAR压缩与解压

    public void RARsave(string rarPatch, string rarFiles,string  patch,string rarName)        {          ...

  9. 小结一下前段时间做的rpgdemo

    虽然说已经是彻底放弃继续做那个demo了(代码结构混乱,想增加新功能非常的不方便),不过还是花了一点心血在里面的,毕竟这是我开始学习unity游戏制作的初衷,不过果然是学的越多越发现自己的不足... ...

  10. android HAL 教程(含实例)

    http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html Android Hal 分析                       ...