slipwindowctrl.java

来自「短信系统SMS:支持普通短信、长短信和wap push短信的发送。」· Java 代码 · 共 128 行

JAVA
128
字号
package com.ekun.common.sms;

import java.util.*;

import com.ekun.common.log.*;

public class SlipWindowCtrl
{
  private static Logger logger = LoggerFactory.getLogger(SlipWindowCtrl.class);
  //滑动窗口大小,即:以发送但没有收到应答的包个数。
  private int slipWindowSize = 16;
  //等待响应的超时,单位:毫秒,一般情况下,对于超时的需要重新发送!
  private int waitACKTimeout = 60 * 1000;
  private HashMap hsPending;
  public SlipWindowCtrl()
  {
    hsPending = new HashMap(100);
  }
  /**
   * 加入未决队列,等待ACK返回
   * @param key String
   * @param objReq SmsInfo:要加入滑动窗口的request对象!
   * @param isBlock int[]: 滑动窗口是否阻塞
   * @return SmsInfo: 正常情况下返回null,若response比较快是,可能在req写入到滑动队列前已经等待,此时,返回等待的对象!
   */
  public synchronized SmsInfo pushCMDPending(String key, SmsInfo objReq)
  {
    try
    {
      //记录进入时间
      objReq.liveTime = System.currentTimeMillis();
      //step 1:察看队列中是否已经有返回的数据!
      SmsInfo myobj = (SmsInfo) hsPending.remove(key);
      //如果没有,则证明respose还没有返回!(正常情况下应该这样!)
      if(myobj == null)
      {
        //加入未决队列
        this.hsPending.put(key, objReq);
        //若超过滑动窗口大小限制,则等待ACK返回.
        if (hsPending.size() > this.slipWindowSize)
        {
          wait(waitACKTimeout);
        }
      }
      else
      {
        //如果此时response已经返回,则直接notify并返回。
        return myobj;
      }
    }
    catch (InterruptedException ex)
    {
      logger.error("SlipWindowCtrld.pushCMDPending Error:" + ex.getMessage(),
                   ex);
    }
    return null;
  }

  /**
   * 当收到ACK后查找原来的请求,若查到通知滑动窗口继续接受,否则丢弃!
   * @param key String
   * @param smsInfo SmsInfo:此参数只为CMPP可用,用以在Response早与request进入的情况下,记录submit response回来后的MsgID。
   * @return SmsInfo
   */
  public synchronized SmsInfo popPending(String key, SmsInfo smsInfo)
  {
    //从未决队列中删除
    SmsInfo myobj = (SmsInfo) hsPending.remove(key);
    //若未决队列中没有匹配到,则可能是ACK先到,加入未决队列!
    if (null == myobj)
    {
      smsInfo.liveTime = System.currentTimeMillis();
      hsPending.put(key, smsInfo);
      logger.debug("滑动窗口没有匹配到返回的数据,可能response早于request到达! Key: " + key);
    }
    notifyAll();
    return myobj;
  }

  /**
   * 取出所有未决的对象! 当重新建立连接时或者阻塞超时时,取出并重新发!
   * @return Object[]
   */
  public synchronized ArrayList getPending()
  {
    Iterator it = hsPending.values().iterator();
    SmsInfo myobj = null;
    ArrayList alist = new ArrayList();
    boolean havePend = false;
    while (it.hasNext())
    {
      myobj = (SmsInfo) it.next();
      if(myobj == null)
      {
        it.remove();
        havePend = true;
        continue;
      }
      //判断是否超时!
      if ((System.currentTimeMillis() - myobj.liveTime) >= waitACKTimeout)
      {
        it.remove();
        havePend = true;
        alist.add(myobj);
      }
    }
    if(havePend)
      notifyAll();
    return alist;
  }

  public int getPendingSize()
  {
    return hsPending.size();
  }

  public int getSlipWindowSize()
  {
    return slipWindowSize;
  }

  public void setSlipWindowSize(int slipWindowSize)
  {
    this.slipWindowSize = slipWindowSize;
  }

}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?