liurunyu
2024-05-16 f3d3eacf5af65ebfcfcc3b82e7488401ac545453
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package com.dy.common.mw.protocol;
 
import java.util.Collection;
import java.util.HashMap;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
 
import com.dy.common.util.ByteUtil;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableHandle;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableStatus;
 
public class PrefixedDataAvailableHandleImp implements PrefixedDataAvailableHandle {
    
    private static final Logger log = LogManager.getLogger(PrefixedDataAvailableHandleImp.class) ;
    
 
    /**
     * 在多线程环境中运行
     * 分析上线数据(网络连接后第一包数据)是否可获得
     * @param in IoBuffer
     * @return PrefixedDataAvailableStatus
     */
    public PrefixedDataAvailableStatus forOnLine(IoBuffer in){
        int remain = in.remaining() ;
        if(remain == 0){
            return new PrefixedDataAvailableStatus().breaked() ;
        }else{
            try{
                PrefixedDataAvailableStatus pds = null ;
                
                HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
                Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
                if(set.size() == 0){
                    throw new Exception("上线数据完整性检查时,得到的协议完整性检查类集合为空。") ;
                }
                int priority = ProtocolConstant.firstPriority ;
 
                while(true){
                    Object[] objs = this.getClassObjAndAnnotationVo(priority, set) ;
                    PrefixedDataAvailable pda = (PrefixedDataAvailable)objs[0] ;
                    if(pda == null && priority == ProtocolConstant.firstPriority){
                        throw new Exception("上线数据完整性检查时,未得到优先级为" + priority + "上线数据完整性检查类!") ;
                    }else if(pda == null){
                        //说明上线数据完整性检查类集合已经遍历完了。
                        break ;
                    }
                    //处理完整性检查
                    pds = pda.forOnLine(in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).onLineDataMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                    //用完对象后,放回池中
                    PrefixedDataAvailablePool.freeInstance(((AnnotationPrefixedDataAvailableVo)objs[1]).clazz, pda);
                    if(pds == null){
                        //说明不是对应的协议数据,需要另外的协议来处理上线
                        //循环继续
                        priority++ ;
                    }else{
                        //停止循环,返回结果
                        break ;
                    }
                }
                if(pds == null){
                    //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据
                    byte[] preByte = new byte[remain];
                    in.get(preByte) ;
                    in.position(0) ;
                    log.error("上线第一包数据未找到对应的解析协议。数据是:" + ByteUtil.bytes2Hex(preByte, true)) ;
                    //认为是完整包数据,后续读出,防止占用内存及死循环IO读数据
                    pds = new PrefixedDataAvailableStatus().rubbish(remain) ;
                }
                return pds ;
            }catch(Exception e){
                //处理过程中发生异常,上行数据就是垃圾数据了,后续以垃圾数据处理,即把数据从IO中取出来,以防止死循环IO读数据
                return new PrefixedDataAvailableStatus().rubbish(remain) ;
            }
        }
    }
 
    /**
     * 在多线程环境中运行
     * 分析上行数据(网络连接后第二(包含)包以后数据)是否可获得
     * @param in IoBuffer
     * @return PrefixedDataAvailableStatus
     */
    public PrefixedDataAvailableStatus forUpData(IoBuffer in){
        int remain = in.remaining() ;
        if(remain == 0){
            return new PrefixedDataAvailableStatus().breaked() ;
        }else{
            try{
               PrefixedDataAvailableStatus pds = null ;
                
                HashMap<String, AnnotationPrefixedDataAvailableVo> prefixedDataAvailableMap = ProtocolCache.getPrefixedDataAvailableMap() ;
                Collection<AnnotationPrefixedDataAvailableVo> set = prefixedDataAvailableMap.values() ;
                if(set.size() == 0){
                    throw new Exception("上线数据完整性检查时,得到的协议集合为空。") ;
                }
                int prority = ProtocolConstant.firstPriority ;
 
                while(true){
                    Object[] objs = this.getClassObjAndAnnotationVo(prority, set) ;
                    PrefixedDataAvailable pda = (PrefixedDataAvailable)objs[0] ;
                    if(pda == null && prority == ProtocolConstant.firstPriority){
                        throw new Exception("上线数据完整性检查时,未得到优先级为" + prority + "上线数据完整性检查类!") ;
                    }else if(pda == null){
                        //说明上线数据完整性检查类集合已经遍历完了。
                        break ;
                    }
                    //处理完整性检查
                    pds = pda.forUpData(in, remain, ((AnnotationPrefixedDataAvailableVo)objs[1]).headMinLength, ((AnnotationPrefixedDataAvailableVo)objs[1]).errorMaxLength) ;
                    //用完对象后,放回池中
                    PrefixedDataAvailablePool.freeInstance(objs[0].getClass(), pda);
                    if(pds == null){
                        //说明不是对应的协议数据,需要另外的协议来处理上线
                        //循环继续
                        prority++ ;
                    }else{
                        //停止循环,返回结果
                        break ;
                    }
                }
                if(pds == null){
                    //说明数据不属于任何协议,一般为Rtu数据出错,或网络攻击数据
                    byte[] preByte = new byte[remain];
                    in.get(preByte) ;
                    in.position(0) ;
                    log.error("上行数据未找到对应的解析协议。数据是:" + ByteUtil.bytes2Hex(preByte, true)) ;
                    //认为是完整包数据,后续读出,防止占用内存及死循环IO读数据
                    pds = new PrefixedDataAvailableStatus().rubbish(remain) ;
                }
                return pds ;
            }catch(Exception e){
                //处理过程中发生异常,上行数据就是垃圾数据了,后续以垃圾数据处理,即把数据从IO中取出来,以防止死循环IO读数据
                return new PrefixedDataAvailableStatus().rubbish(remain) ;
            }
         }        
    }
    
 
 
    /**
     * 得到处理类对象
     * @param prority 优先级
     * @param set 集合
     * @return Object[]
     * @throws Exception 异常
     */
    private Object[] getClassObjAndAnnotationVo(int prority, Collection<AnnotationPrefixedDataAvailableVo> set) throws Exception{
        PrefixedDataAvailable obj = null ;
        AnnotationPrefixedDataAvailableVo rVo = null ;
        for(AnnotationPrefixedDataAvailableVo vo : set){
            if(prority == vo.priority){
                obj = PrefixedDataAvailablePool.getInstance(vo.clazz) ;
                rVo = vo ;
                break ;
            }
        }
        return new Object[]{obj, rVo} ;
    }
 
}