/**
   * * 解析从服务器收到的包,切割完整包,并返回半包
   *
   * @param unHandledPkg 从socket收到的数据包
   * @param parser 不同的协议,传递不同的包内容解析器
   * @return 如果收到的包是一个或者多个完整包,那么返回0长度字节数组 如果收到的包是1个半或者N个半数据包,那么截取一个或N个完整包,并把剩余的部分返回
   */
  private final byte[] handlePackage(byte[] unHandledPkg, IPackageContenParser parser) {
    /** 调用一次read,从Server收到的数据包(可能是半包、1个包、1.x、2.x....) */
    int pkgLen = unHandledPkg.length;

    /** 一个完整数据包的长度 */
    int completePkgLen = parser.getCompletePackageLength(unHandledPkg);

    if (completePkgLen > pkgLen) {
      /** 当前收到的数据不到一个完整包,则直接返回,等待下一个包 */
      return unHandledPkg;
    } else if (completePkgLen == pkgLen) {
      /** 一个完整包,则直接丢到已处理队列 */
      handledQueue.offer(unHandledPkg);

      return EmptyContainer.EMPTY_BYTE_ARRAY;
    } else {
      /** 有多个包,那么就递归解析, */
      byte[] onePkg = parser.getCompletePackage(unHandledPkg);
      handledQueue.offer(onePkg);

      /** 截取除完整包后的剩余部分 */
      byte[] remain = PackageTools.getSubBytes(unHandledPkg, onePkg.length, pkgLen - onePkg.length);

      return handlePackage(remain, parser);
    }
  }
  private final void loopAndHandlePackage(final IPackageContenParser parser) throws IOException {
    int bytesRead = -1;
    /** remains保存解析出完整包后剩余的部分 */
    byte[] remains = EmptyContainer.EMPTY_BYTE_ARRAY;

    while (!stopReceive) {

      try {
        while ((bytesRead = in.read(buffer)) != -1) {

          byte[] temp = new byte[bytesRead];
          System.arraycopy(buffer, 0, temp, 0, bytesRead);

          if (remains.length > 0) {
            /**
             * 剩余部分的长度大于0,表明有上一次处理后,还有剩余部分未处理,那么把收到的包和这个半包合并成一个新包(上一次包的数据在前)
             * 第一次执行时,因为remains长度为0,所以跳过了这个判断内的语句,然后解析第一个包,如果有剩余就组合
             */
            temp = PackageTools.combinePackage(remains, temp);
          }

          remains = handlePackage(temp, parser);
        }
      } catch (IOException e) {
        if ("socket closed".equalsIgnoreCase(e.getMessage())) {
          // 关闭时,因为read方法还在阻塞中,所以要抛出这个异常,这是正常的,所以不处理
        } else {
          e.printStackTrace();
        }
      }

      Sleeper.sleepSomeMilliseconds(50);
    }
  }