Rime协议学习笔记:(四)标识广播broadcast

来源:互联网 发布:java 当前时间加1小时 编辑:程序博客网 时间:2024/05/14 20:25

四.标识广播broadcast


  broadcast源码文件:contiki-3.0/core/net/rime/broadcast.[c/h]。
  根据broadcast.h中的官方注释理解如下:标识广播模块将数据包发送给所有的本地邻居节点,这些节点都含有一个识别发送者的头标(header)。该模块增加了单跳发送者的地址作为一个数据包属性到传出的数据包,所有的Rime原语使用broadcast原语根据收到的数据包来识别发送方的地址。


4.1 broadcast相关定义

broadcast相关结构体:

struct broadcast_conn {/**代表一个broadcast连接 */  struct abc_conn c;/*包含一个abc连接,即broadcast建立在abc基础上,由abc抽象而来,可理解为面向对象里类的继承与派生*/  const struct broadcast_callbacks *u;//回调函数};struct broadcast_callbacks {/**Called when a packet has been received by the broadcast module.*//**broadcast回调*/  void (* recv)(struct broadcast_conn *ptr, const linkaddr_t *sender);/*接收数据包,对比3.1abc的recv,多了一个发送者地址参数,即broadcast与abc的区别*/  void (* sent)(struct broadcast_conn *ptr, int status, int num_tx);//发送数据包};

broadcast数据包相关属性:

/**broadcast.h中的定义*/#define BROADCAST_ATTRIBUTES  { PACKETBUF_ADDR_SENDER, PACKETBUF_ADDRSIZE },ABC_ATTRIBUTES//数据包中包含发送者地址,即broadcast的意义所在,区别于abc;//见3.1中ABC_ATTRIBUTES定义为空/**broadcast.c中的定义*/static const struct packetbuf_attrlist attributes[]={BROADCAST_ATTRIBUTES  PACKETBUF_ATTR_LAST};

4.2 主要操作

4.2.1 回调函数

   用户自定义回调函数:由用户在使用broadcast时自己定义并调用,调用时封装在broadcast_callbacks里,即broadcast的回调类型。(详见4.3broadcast实例中的使用方法)
  系统回调函数为:接收回调recv_from_abc和发送回调sent_by_abc。调用系统回调函数时封装在abc_callbacks里,即abc的回调类型。具体代码如下:

static const struct abc_callbacks broadcast = {recv_from_abc, sent_by_abc};static void recv_from_abc(struct abc_conn *bc){/**系统定义接收回调函数,即接收来自abc的数据包*/  linkaddr_t sender;  struct broadcast_conn *c = (struct broadcast_conn *)bc;  linkaddr_copy(&sender, packetbuf_addr(PACKETBUF_ADDR_SENDER));//设置发送者  PRINTF("%d.%d: broadcast: from %d.%d\n",        linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1], //接收者自己的地址        sender.u8[0], sender.u8[1]); //发送者地址  if(c->u->recv) {    c->u->recv(c, &sender);  }}static void sent_by_abc(struct abc_conn *bc, int status, int num_tx){/**系统定义发送回调函数,即调用abc发送数据包*/  struct broadcast_conn *c = (struct broadcast_conn *)bc;  PRINTF("%d.%d: sent to %d.%d status %d num_tx %d\n",        linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1], //发送者自己的地址        packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],        packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1], //利用packetbuf_addr返回发送者地址        status, num_tx);  if(c->u->sent) {    c->u->sent(c, status, num_tx);  }}

4.2.2 broadcast_open

void broadcast_open(struct broadcast_conn *c, uint16_t channel, const struct broadcast_callbacks *u){/**打开一个broadcast广播,并打开系统定义的回调函数*/  abc_open(&c->c, channel, &broadcast);//打开一个abc连接  c->u = u;//用broadcast_callbacks代替abc_callbacks  channel_set_attributes(channel, attributes);}

4.2.3 broadcast_close

void broadcast_close(struct broadcast_conn *c){/**关闭一个broadcast广播*/  abc_close(&c->c);//调用abc_close,实际上就是关闭广播通道}

4.2.4 broadcast_send

int broadcast_send(struct broadcast_conn *c){/**发送broadcast广播,即调用abc发送数据*/PRINTF("%d.%d: broadcast_send\n",linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]); //发送者自己的地址packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);//将发送者的地址传入packetbuf_addr  return abc_send(&c->c);//调用abc_send发送数据包}

4.3 broadcast广播实例

4.3.1 官方实例源码

  利用两个节点相互发送并接收对方的数据:

#include "contiki.h"#include "net/rime.h"#include "random.h"#include "dev/button-sensor.h"#include "dev/leds.h"#include <stdio.h>PROCESS(example_broadcast_process, "Broadcast example");AUTOSTART_PROCESSES(&example_broadcast_process);/*broadcast_recv回调函数:接收broadcast广播*/static void broadcast_recv(struct broadcast_conn *c, const rimeaddr_t *from){  printf("broadcast message received from %d.%d: '%s'\n",         from->u8[0], from->u8[1], (char *)packetbuf_dataptr());}static const struct broadcast_callbacks broadcast_call = {broadcast_recv};//调用回调函数static struct broadcast_conn broadcast;PROCESS_THREAD(example_broadcast_process, ev, data){  static struct etimer et;  PROCESS_EXITHANDLER(broadcast_close(&broadcast);)  PROCESS_BEGIN();  broadcast_open(&broadcast,129,&broadcast_call);//打开broadcast广播,此处会打开系统定义的回调  while(1) {    /* Delay 2-4 seconds */    etimer_set(&et, CLOCK_SECOND * 4 + random_rand() % (CLOCK_SECOND * 4));    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));    packetbuf_copyfrom("Hello", 6);    broadcast_send(&broadcast); //发送broadcast广播    printf("broadcast message sent\n");  }  PROCESS_END();}

4.3.2 Cooja仿真测试

  (1)在unicast.c中将调试信息打开,如图,将图中的0改为1:
这里写图片描述
  (2)利用Cooja仿真器仿真broadcast的结果如下,可以观察到节点每次收到数据时会识别出发送者的地址。仿真实验中主要根据节点接收和发送数据包时的输出信息来追踪打印这些输出信息的函数,从而清晰地认识broadcast的通信过程。
这里写图片描述
这里写图片描述

4.3.3 CC2538实测

  (1)在unicast.c中将调试信息关闭
  (2)利用CC2538节点实测broadcast,此处主要观察两个节点收发数据包的结果,结果如下:
这里写图片描述

0 0
原创粉丝点击