recv函数有两个作用,不仅是接收其他节点发送的包,而且当节点接收到其他包的时候也会调用recv()

首先给出NS2中recv的源码,和一些注释:

 void
Mac802_11::recv(Packet *p, Handler *h)
{
struct hdr_cmn *hdr = HDR_CMN(p);
/*
* Sanity Check
*/
assert(initialized()); /*
* Handle outgoing packets.
*/
if(hdr->direction() == hdr_cmn::DOWN) {//向下传输,也就是节点要向外发送,故调用recv()
send(p, h);

return;
}
/*
* Handle incoming packets.
*
* We just received the 1st bit of a packet on the network
* interface.
*
*/ /*
* If the interface is currently in transmit mode, then
* it probably won't even see this packet. However, the
* "air" around me is BUSY so I need to let the packet
* proceed. Just set the error flag in the common header
* to that the packet gets thrown away.
*/
if(tx_active_ && hdr->error() == ) {//如果当前正在发送的话则标记为错误,这个数据包会在后面的函数中被处理掉
hdr->error() = ;
} if(rx_state_ == MAC_IDLE) {//如果当前空闲则设置为接收态
setRxState(MAC_RECV);
pktRx_ = p;
/*
* Schedule the reception of this packet, in
* txtime seconds.
*/
if (mhProbe_.busy() && OnMinChannelTime) {
Recv_Busy_ = ; // Receiver busy indication for Probe Timer
} mhRecv_.start(txtime(p));
} else {
/*
* If the power of the incoming packet is smaller than the
* power of the packet currently being received by at least
* the capture threshold, then we ignore the new packet.
*/
if(pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh) {//有冲突发生时,如果新到的包功率比较小,信噪比在阀值以下的时候调用capture函数,主要作用是
capture(p);
} else {//冲突比较大的时候需要调用冲突函数
collision(p);
}
}

  总结一下recv函数的工作流程主要是以下一些阶段:

  1、判断这个包是要发出去的还是收到的,发出去的直接调用send函数就行;

  2、判断MAC的状态,如果是发送态就直接将这个包标记为错误(这个错误会在后面处理),如果是空闲状态,则这个时候可以正常接收数据包,将MAC状态转换成MAC_RECV状态然后保存定时器(定时器的作用是NS2模拟发包过程,当定时器为零才发送完成)

  3、如果MAC不是空闲,我们正在接收其他的包,那么我们需要判断这时新到的包是否会影响到原来正在接收的,也就是计算信噪比与阀值比较,当在阀值以下的时候我们忽略这个包(调用capture),否则产生冲突。

但是这两个函数也不是十分简单的。首先看capture:

 void
Mac802_11::capture(Packet *p)
{
/*
* Update the NAV so that this does not screw
* up carrier sense.
*/
set_nav(usec(phymib_.getEIFS() + txtime(p)));
Packet::free(p);
}

   这段代码的作用是当新到达的包不会对原来的接收造成影响的时候,将这个包作为一个多余的信息丢掉,即free。但是还有一个设置NAV的值为EIFS+这个数据包传输时间,关于这一点我的理解是:假设这个节点顺利完成了当前的接收任务,如果说干扰包的发送还是没有完成的话,必然会再次收到它的信号,但是这个信号必然是无效的,所以直接设置NAV可以避开这个问题。

再看collision:

 void
Mac802_11::collision(Packet *p)
{
switch(rx_state_) {
case MAC_RECV:
setRxState(MAC_COLL);
/* fall through */
case MAC_COLL:
assert(pktRx_);
assert(mhRecv_.busy());
/*
* Since a collision has occurred, figure out
* which packet that caused the collision will
* "last" the longest. Make this packet,
* pktRx_ and reset the Recv Timer if necessary.
*/
if(txtime(p) > mhRecv_.expire()) {
mhRecv_.stop();
discard(pktRx_, DROP_MAC_COLLISION);
pktRx_ = p;
mhRecv_.start(txtime(pktRx_));
}
else {
discard(p, DROP_MAC_COLLISION);
}
break;
default:
assert();
}

这一段代码主要是完成冲突的处理:

1、判断如果是正常接收状态,到这应该应经是冲突发生了,所以我们要改变MAC的状态。

2、在冲突状态下,他这采取了选择接收结束时间按比较晚的那个包(但是这个包最终也会因为冲突发生被丢弃),至于原因感觉跟上面差不多既然冲突发生了,即使后来可以接收到一部分正确的包,但是意义也不大,所以直接用接收一个时间较长的把这段跳过去。

  这就是recv的大概过程了,牵涉的其他细节由于暂时没有用到就没有深究了。我理解不对的地方欢迎指正。

最新文章

  1. Sql Server系列:数据表操作
  2. [转] JS中简单的继承与多态
  3. iOS7中的ViewController切换
  4. BFGS方法
  5. HDU 1711 Number Sequence(KMP匹配数字串)
  6. Vue.js 系列教程 ①
  7. xmlplus 组件设计系列之七 - 路由
  8. Cleaner, more elegant, and wrong(翻译)
  9. Jenkins + Gradle + pgyer + Android自动发布
  10. 论文阅读笔记四十:Deformable ConvNets v2: More Deformable, Better Results(CVPR2018)
  11. Vue组件间的参数传递
  12. dll 恐怖的代码调整
  13. 中秋节福利---HTML5-玉兔吃月饼游戏
  14. web api解决序列化后返回标准时间带T问题
  15. 配置 tsconfig.json
  16. 神经网络中Epoch、Iteration、Batchsize相关理解
  17. golang C相互调用带参数
  18. python--函数名的使用,闭包,迭代器
  19. Java Ioc详解和实现
  20. CRM系统知识点之一权限(RBAC)

热门文章

  1. GitHub访问速度慢的解决方法
  2. JS添加删除DIV
  3. iOS 8 WKWebView
  4. MySQL中的增删改查
  5. 安装CentOS 7时出现No Caching mode page found问题的解决
  6. ACM/ICPC 之 两道dijkstra练习题(ZOJ1053(POJ1122)-ZOJ1053)
  7. ALV 输入数据时数字缩小一千倍的问题解决
  8. Effective C++ -----条款23:宁以non-member、non-friend替换member函数
  9. codeforces 490C. Hacking Cypher 解题报告
  10. 【leetcode】Reverse Linked List II (middle)