📜  Ad Hoc网络中公平信道访问的增强二进制指数退避算法。(1)

📅  最后修改于: 2023-12-03 15:29:17.425000             🧑  作者: Mango

Ad Hoc网络中公平信道访问的增强二进制指数退避算法

简介

Ad Hoc网络是指由无线设备直接组成的临时网络,这些设备一般是移动设备或车载设备等。在这种网络中,设备之间通常通过广播方式进行通信,因此存在信道竞争的问题。

为了提高Ad Hoc网络中信道的利用率和公平性,研究人员提出了很多调度算法。其中,二进制指数退避算法是一种经典的调度算法。

本文将介绍一种增强的二进制指数退避算法,在Ad Hoc网络中实现公平信道访问。

算法原理

二进制指数退避算法是一种随机化算法,它的基本思想是:

  • 当一个节点需要发送数据时,它会在一个随机的时间片内进行发送
  • 如果该时间片内信道被占用,则等待一段随机时间后再重试

这种算法的优点是简单易实现,缺点是可能会造成较严重的公平性问题。因为等待时间是随机的,有些节点可能会等待过长时间,造成其它节点的数据发送被延迟。

为了解决这个问题,研究人员提出了增强的二进制指数退避算法。该算法在二进制指数退避算法的基础上增加了下列特性:

  • 当某个节点在等待发送数据时,如果它发现其它节点正在等待发送数据,则它会在其它节点等待的时间上加上一个固定的常数,以减少等待时间过长的问题。
  • 当某个节点成功发送数据后,它会通知其它节点,在下一次调度时,其它节点的等待时间将加上发送节点发送数据的时间,以实现公平性。
实现细节
初始化

在算法开始前,需要初始化一些参数:

  • $CW_{min}$:最小退避窗口
  • $CW_{max}$:最大退避窗口
  • $m$:最大重试次数
  • $currRetry$:当前重试次数
  • $currCW$:当前退避窗口
  • $accTime$:累计等待时间
等待发送

当某个节点需要发送数据时,它需要按以下步骤执行:

  1. 生成一个[0, $2^{currCW} - 1$]之间的随机数$r$,该随机数表示等待时间的时间片
  2. 如果信道未被占用,则在$r$个时间片后进行发送
  3. 如果信道被占用,则从当前时间开始,等待$r$个时间片后,再尝试发送
  4. 如果当前重试次数$currRetry$小于最大重试次数$m$,则将$currRetry$加1,$currCW$加1,并重新执行步骤1;否则,等待时间定为$2^{currCW} - 1$,并重新执行步骤1

注意:信道被占用是指在$r$个时间片内,信道一直处于占用状态。

更新等待时间

当某个节点成功发送数据后,它需要广播一个消息,让其它节点更新等待时间。更新等待时间的步骤如下:

  1. 将等待时间累加上发送数据的时间
  2. 如果等待时间大于最大等待时间$2^{CW_{max}} - 1$,则将等待时间定为$2^{CW_{max}} - 1$
  3. 如果有其他节点正在等待发送数据,则将其等待时间加上一个固定的常数,即$accTime / n$,其中$n$表示正在等待发送数据的节点数
超时未成功发送

如果某个节点在等待发送数据的过程中,累计等待时间$accTime$超过了某个阈值$T$,仍未成功发送数据,则需要执行以下步骤:

  1. 将$currRetry$加1
  2. 如果$currRetry$小于$m$,则将$currCW$加1,并重新执行等待发送的步骤;否则,等待时间定为$2^{CW_{max}} - 1$,并重新执行等待发送的步骤
代码实现

以下是增强的二进制指数退避算法的代码实现,语言为Java:

public class BinaryExponentialBackoffAlgorithm {
  
  // 最小退避窗口大小
  private final int CW_MIN = 1;
  
  // 最大退避窗口大小
  private final int CW_MAX = 8;
  
  // 最大重试次数
  private final int MAX_RETRY = 5;
  
  // 当前重试次数
  private int currRetry;
  
  // 当前退避窗口大小
  private int currCW;
  
  // 累计等待时间
  private long accTime;
  
  // 等待发送数据
  public void waitToSend() {
    int r = getRandom(0, (int) Math.pow(2, currCW) - 1);
    boolean success = false;
    do {
      // 等待r个时间片
      waitFor(r);
      if (isChannelIdle()) {
        // 信道空闲,发送数据
        success = true;
        send();
      } else {
        // 信道占用,等待r个时间片后再试
        r = getRandom(0, (int) Math.pow(2, currCW) - 1);
      }
    } while (!success && currRetry++ < MAX_RETRY);
    if (!success) {
      // 超时未成功发送
      currCW = Math.min(currCW + 1, CW_MAX);
      currRetry = 0;
      if (accTime >= T) {
        accTime = 0;
        currRetry++;
      }
      waitToSend();
    }
  }
  
  // 更新等待时间
  public void updateWaitTime(long sendTime, int numWaitingNodes) {
    accTime += sendTime;
    if (accTime > Math.pow(2, CW_MAX) - 1) {
      accTime = (int) Math.pow(2, CW_MAX) - 1;
    }
    if (numWaitingNodes > 1) {
      accTime += accTime / numWaitingNodes;
    }
  }
  
  // 等待指定时间片
  private void waitFor(int time) {
    // TODO
  }
  
  // 发送数据
  private void send() {
    // TODO
  }
  
  // 判断信道是否空闲
  private boolean isChannelIdle() {
    // TODO
  }
  
  // 生成指定区间内的随机数
  private int getRandom(int min, int max) {
    // TODO
  }
}

代码中有些细节需要根据具体情况实现,比如等待指定时间片、发送数据和判断信道是否空闲这些函数。但是,大部分逻辑都已经在代码中给出了。