| package com.dy.common.mw.protocol.p206V1_0_0; | 
|   | 
| 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; | 
|   | 
|   | 
| @AnnotationPrefixedDataAvailable( | 
|         enable = true, | 
|         protocolName = ProtocolConstantV206V1_0_0.protocolName, | 
|         priority = ProtocolConstantV206V1_0_0.priority, | 
|         onLineDataMinLength = ProtocolConstantV206V1_0_0.onLineDataMinLength, | 
|         headMinLength = ProtocolConstantV206V1_0_0.headMinLength) | 
| @SuppressWarnings("unused") | 
| public class PrefixedDataAvailableV1_0_1 implements PrefixedDataAvailable { | 
|   | 
|     private static final Logger log = LogManager.getLogger(PrefixedDataAvailableV1_0_1.class) ; | 
|      | 
|     private static final String protocolName = ProtocolConstantV206V1_0_0.protocolName ; | 
|   | 
|   | 
|     /** | 
|      * 分析上线数据(网络连接后第一包数据)是否可获得 | 
|      * @param in IoBuffer | 
|      * @param remain 一定时大于0的数据 | 
|      * @param minDataLength 最小数据长度 | 
|      * @param maxDataLength 最大数据长度,达到或超过此长度,认为是垃圾数据。例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据 | 
|      * @return 不是本协议数据时返回空 | 
|      * @throws Exception 异常 | 
|      */ | 
|     public PrefixedDataAvailableStatus forOnLine(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(preByte, minDataLength, maxDataLength) ; | 
|     } | 
|   | 
|     /** | 
|      * 分析上线后(网络连接后非第一包数据)是否可获得 | 
|      * @param in IoBuffer | 
|      * @param remain  剩余 | 
|      * @param minDataLength 最小数据长度 | 
|      * @param maxDataLength 最大数据长度 | 
|      * @return PrefixedDataAvailableStatus | 
|      * @throws Exception 异常 | 
|      */ | 
|     @Override | 
|     public PrefixedDataAvailableStatus forUpData(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(preByte, minDataLength, maxDataLength) ; | 
|   | 
|     } | 
|     /** | 
|      * 进行判断 | 
|      * @param preByte byte[] | 
|      * @param minDataLength 最小数据长度 | 
|      * @param maxDataLength 最大数据长度 | 
|      * @return PrefixedDataAvailableStatus | 
|      * @throws Exception 异常 | 
|      */ | 
|     private PrefixedDataAvailableStatus doForData(byte[] preByte, int minDataLength, int maxDataLength) throws Exception{ | 
|         int remain = preByte.length ; | 
|          | 
|         if (remain < minDataLength) { | 
|             log.warn("基于协议(" + protocolName + ")判断数据头部发生断包现象。") ; | 
|             return new PrefixedDataAvailableStatus().breaked() ; | 
|         } | 
|          | 
|         if(remain >= maxDataLength){ | 
|             //超出了最大长度限制,例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据 | 
|             return new PrefixedDataAvailableStatus().rubbish(remain) ; | 
|         } | 
|   | 
|          | 
|         CommonV1_0_1 parseCommon = new CommonV1_0_1(); | 
|         boolean isThisProtocolData = parseCommon.isThisProtocolHead(preByte) ; | 
|   | 
|         if(!isThisProtocolData){ | 
|             //不是本协议数据 | 
|             return null ; | 
|         } | 
|   | 
|         Integer dataLen = parseCommon.parseFrameLen(preByte) ; | 
|   | 
|         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) ; | 
|         }else if(remain > dataLen){ | 
|             String headHex = ByteUtil.bytes2Hex(preByte, true) ; | 
|             log.warn("收到数据之帧前部:" + headHex + ",但发生粘包现象。") ; | 
|             return new PrefixedDataAvailableStatus().adjoined(dataLen) ; | 
|         }else{ | 
|             // remain < dataLen | 
|             String headHex = ByteUtil.bytes2Hex(preByte, true) ; | 
|             log.warn("收到数据之帧前部:" + headHex + ",但发生断包现象。") ; | 
|             return new PrefixedDataAvailableStatus().breaked() ; | 
|         } | 
|     } | 
|   | 
| } |