仅供参考.
/****************************************************************************************************************************/
event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m){
int i;
uint8_t seg;
if(TOS_LOCAL_ADDRESS==Des_Node){
dbg(DBG_TEMP|DBG_USR1,"timer stop 1");
call Timer.stop();
recvPack=(struct myPack *)m->data;
pnum=recvPack->packnum;
seg=(pnum-1)%10*20;
if(packLabel[pnum]==FALSE){
for(i=0;i<20;i++){
des_buffer[i+seg]=recvPack->data[i];
}
buf_cnt+=20;
packLabel[pnum]=TRUE;
}
dbg(DBG_TEMP|DBG_USR1,"buf_cnt=%d",buf_cnt);
if(buf_cnt==200){//完整的接收到一批数据包(1批数据包为10个,每个数据包有20个字节)
ackPack->acknum=(ackPack->acknum+1)%256;
buf_cnt=0;
sendAck((pnum-1)/10*10);
call Leds.yellowToggle();
dbg(DBG_TEMP|DBG_USR1,"timer start 1");
call Timer.start(TIMER_REPEAT,50);
signal MyRouting.packReceiveDone(des_buffer);
}
else{
ackPack->acknum=(ackPack->acknum+1)%256;
dbg(DBG_TEMP|DBG_USR1,"timer start 2");
call Timer.start(TIMER_REPEAT,1000);
}
}
else if(TOS_LOCAL_ADDRESS==Source_Node){
tempPack=(struct myPack *)m->data;
if(ackPack->acknum!=tempPack->acknum){
ackPack->packSort=tempPack->packSort;
ackPack->last=tempPack->last;
ackPack->acknum=tempPack->acknum;
ackPack->packnum=tempPack->packnum;
for(i=0;i<20;i++){
ackPack->data[i]=tempPack->data[i];
}
retransmit();
}
}
else{
//在路由表中判断是否进行转发
}
return m;
}
/****************************************************************************************************************************/
以上是本人写的部分代码,注意代码中的红色部分.
熟悉TinyOs的人应该知道,这个事件是GennericComm接口声明的event,作用是收到无线数据报之后的通知.
本段函数的目的是在收到源节点图片数据包之后,做相应的处理.
蓝色字体部分的意思是在收完一批数据包(10组)之后,通知网络层以上执行相应动作.问题就出在这一段中了.
上一批数据收完之后,下一批数据很快就会来到.但当下一批数据中的第一个数据包过来的时候,
这时红色代码call Timer.start(TIMER_REPEAT,50); 定时器已经启动了(定时器的工作是根据
当前数据包进行计算发送本批数据的ACK),尽管在event开始的时候都会将定时器关掉,但是,
已经开始执行的定时器并不会因此而终止掉,它会执行完本次定时器中的内容,然后才会stop(
一开始不知道,严重被坑!!!,怎么都不会想到这个细节).那么这个时候问题就来了.定时器里的操作
本来应该是根据当前数据包,也就是上一批的最后一个数据包进行进行计算,但这个时候下一批数
据包的第一个报文已经到达,recvPack=(struct myPack *)m->data;被篡改成了下一批数据包的
第一个报文,那么这个时候定时器进行的计算实际上是下一批次的ACK,计算完以后迅速发给源节
点.然而这个时候源节点的这一批报文还没有发送完,怎么能直接先给确认呢?
所以经过TOSSIM的多次模拟,最终把call Timer.start(TIMER_REPEAT,50);中的50改为了100.