pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V2/PrefixedDataAvailableV2.java
New file
@@ -0,0 +1,134 @@
package com.dy.common.mw.protocol.p206V2;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableStatus;
import com.dy.common.mw.protocol.AnnotationPrefixedDataAvailable;
import com.dy.common.mw.protocol.PrefixedDataAvailable;
import com.dy.common.util.ByteUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.BufferDataException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
@AnnotationPrefixedDataAvailable(
      enable = true,
      protocolName = ProtocolConstantV206V2.protocolName,
      protocolVersion = ProtocolConstantV206V2.protocolVer,
      priority = ProtocolConstantV206V2.priority,
      onLineDataMinLength = ProtocolConstantV206V2.onLineDataMinLength,
      headMinLength = ProtocolConstantV206V2.headMinLength)
@SuppressWarnings("unused")
public class PrefixedDataAvailableV2 implements PrefixedDataAvailable {
   private static final Logger log = LogManager.getLogger(PrefixedDataAvailableV2.class) ;
   private static final String protocolName = ProtocolConstantV206V2.protocolName ;
   private static final short protocolVersion = ProtocolConstantV206V2.protocolVer ;
   /**
    * 分析上线数据(网络连接后第一包数据)是否可获得
    * @param in IoBuffer
    * @param remain 一定时大于0的数据
    * @param minDataLength 最小数据长度
    * @param maxDataLength 最大数据长度,达到或超过此长度,认为是垃圾数据。例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据
    * @return 不是本协议数据时返回空
    * @throws Exception 异常
    */
   public PrefixedDataAvailableStatus forOnLine(IoSession ioSession,
                                     IoBuffer in,
                                     int remain,
                                     int minDataLength, //对应ProtocolConstantV2_0.onLineDataMinLength
                                     int maxDataLength //对应ProtocolConstant.errorMaxLength
                                     ) throws Exception {
      int oldPosition = in.position() ;
      byte[] preByte = new byte[remain];
      in.get(preByte) ;
      //in.position(0) ;//错误用法,如果发生粘包数据,将会死循环
      in.position(oldPosition) ;
      return this.doForData(ioSession, preByte, minDataLength, maxDataLength) ;
   }
   /**
    * 分析上线后(网络连接后非第一包数据)是否可获得
    * @param in IoBuffer
    * @param remain  剩余
    * @param minDataLength 最小数据长度
    * @param maxDataLength 最大数据长度
    * @return PrefixedDataAvailableStatus
    * @throws Exception 异常
    */
   @Override
   public PrefixedDataAvailableStatus forUpData(IoSession ioSession,
                                     IoBuffer in,
                                     int remain,
                                     int minDataLength,
                                     int maxDataLength) throws Exception {
      int oldPosition = in.position() ;
      byte[] preByte = new byte[remain];
      in.get(preByte) ;
      //in.position(0) ;//错误用法,如果发生粘包数据,将会死循环
      in.position(oldPosition) ;
      return this.doForData(ioSession, preByte, minDataLength, maxDataLength) ;
    }
   /**
    * 进行判断
    * @param ioSession ioSession
    * @param preByte byte[]
    * @param minDataLength 最小数据长度
    * @param maxDataLength 最大数据长度
    * @return PrefixedDataAvailableStatus
    * @throws Exception 异常
    */
   private PrefixedDataAvailableStatus doForData(IoSession ioSession, byte[] preByte, int minDataLength, int maxDataLength) throws Exception{
      int remain = preByte.length ;
        if (remain < minDataLength) {
           log.warn("基于协议(" + (protocolName + protocolVersion) + ")判断数据头部发生断包现象。") ;
            return new PrefixedDataAvailableStatus().breaked() ;
        }
        if(remain >= maxDataLength){
         //超出了最大长度限制,例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据
         return new PrefixedDataAvailableStatus().rubbish(remain) ;
      }
        CommonV2 parseCommon = new CommonV2();
      Boolean[] isThisProtocolData = parseCommon.isThisProtocolHead(preByte) ;
      if(isThisProtocolData == null || isThisProtocolData.length != 2 || !isThisProtocolData[0].booleanValue()){
         //不是本协议数据
         return null ;
      }
      Integer dataLen = parseCommon.parseFrameLen(preByte, isThisProtocolData[1]) ;
      if(dataLen == null){
         String headHex = ByteUtil.bytes2Hex(preByte, true) ;
         throw new BufferDataException("收到数据之帧前部:" + headHex + ",但严重错误,在进行断包与粘包检查时,未能得到数据帧的长度。");
      }
        if (dataLen <= 0 || dataLen > maxDataLength) {
         String headHex = ByteUtil.bytes2Hex(preByte, true) ;
            throw new BufferDataException("收到数据之帧前部:" + headHex + ",但严重错误,在进行断包与粘包检查时,数据帧的长度(" + dataLen + ")超出合法范围。");
        }
        if(remain == dataLen){
           //不断不粘
            return new PrefixedDataAvailableStatus().completed(dataLen, protocolName, protocolVersion) ;
        }else if(remain > dataLen){
         String headHex = ByteUtil.bytes2Hex(preByte, true) ;
           log.warn("收到数据之帧前部:" + headHex + ",但发生粘包现象。") ;
            return new PrefixedDataAvailableStatus().adjoined(dataLen, protocolName, protocolVersion) ;
        }else{
           // remain < dataLen
         String headHex = ByteUtil.bytes2Hex(preByte, true) ;
           log.warn("收到数据之帧前部:" + headHex + ",但发生断包现象。") ;
            return new PrefixedDataAvailableStatus().breaked() ;
        }
   }
}