热度 17
2013-7-9 12:58
1016 次阅读|
0 个评论
2013-7-5 19:02 首先关于里边的一个变量: buflen指的是payload(packetbuf的数据部分)的长度, bufptr指的是payload(packetbuf的数据部分)的起始位置; hdrptr指的是报文头的起始位置(在packetbuf的报文头部分); packetbuf实际大小是PACKETBUF_HDR_SIZE+PACKETBUF_SIZE(即默认为128+48)。 关于packetbuf使用缓冲区的方式,以及关于为什么,发送和接收存放不一致,确实值得分析一下。 对于发送而言,报文头使用内存是从后往前,payload是从前往后,是因为在发送时不用再去调整报文头和payload的位置,即使需要调整,也只是根据bufptr将payload调整为以PACKETBUF_HDR_SIZE开始的packetbuf(即报文头的尾部)。方便于组织与打包数据。(现在理解到这个,是因为之前在一次写通信协议的打包的时候,自己也这样做过。现在再看,这里的使用确实很是巧妙,而当时自己只是为了解决一个打包问题,而临时使用的一个方式。当时还以为这样做不可取。没想到,Contiki中整个的数据打包都是基于这种方式。) 对于接收而言,在没有进行解包前,我们不知道哪里是报文头,无法进行分开存放,这样全部放在packetbuf的数据区也是合适的,也正因为这样才有了packetbuf_hdrreduce解包函数,用来提取各自的报文头。 bufptr与buflen作用: 为了在接收数据时,从incoming packet中提取出报文头和数据,即在接收数据解包时找到报文头和数据的起始位置。 因为发送时,报文头和payload是很开放置的,一个放置在packetbuf报文头缓冲区,一个放置在packetbuf数据缓冲区,但是接收回的数据都是在packetbuf数据缓冲区中放置的,所以在提取报文头的时候,将buflen减了size,正好将前size字节的报文头提取出来。而对于bufptr加了size,正好跳过size字节的报文头,而这个时候bufptr指向的位置,正好是下一次要提取的报文头或者payload(即报文中数据部分)的开始。 在接收函数中会先调用packetbuf_hdrreduce(因为发送时的packet_compact,将bufptr已经置为0,所以这里接收到的数据帧放置在PACKETBUF_HDR_SIZE起始的packetbuf中)。这里调用packetbuf_hdrreduce(size),正好将各层自己的报文头提取出来,这里的size正好是每层各自报文头的长度。在packetbuf_hdrreduce(size)函数中, bufptr+=size; buflen-=size; 这样,bufptr的位置,正好是下一次要提取的报文头或者payload的起始地址,而buflen则是剩下的数据长度。 这也既是,为什么在发送函数前会有一个packet_compact,调整数据的存放,将payload放置在PACKETBUF_HDR_SIZE开始的packetbuf中,也即payload的起始地址;在解包函数中,都会有一个packetbuf_hdrreduce,提取报文头。 关于 packetbuf_set_addr() packetbuf_set_attr() 每一层都会设置相应的addr,和attr。channel是在chameleon中设置的。最后在packet_header时,从packetbuf_attrs,packetbuf_addrs静态数组中提取,组织到packetbuf中准备发送; 注: http://blog.chinaunix.net/uid-9112803-id-3277952.html 给了很多启发