فهرست منبع

fix(tcp): XDecoder 半包按期望长度判定,修复 VLDW/MBDW 偶发返回 NS

wangxichen 5 روز پیش
والد
کامیت
2c97d3a84f

+ 21 - 1
src/main/java/com/jeesite/modules/utils/ProtocolParam.java

@@ -109,7 +109,27 @@ public class ProtocolParam {
         }
         return Integer.parseInt(nn);
     }
-    // 获取参数的总长度
+    // 获取参数段的期望总长度:只按报文声明的参数个数计算,不判断数据是否已到齐。
+    // 用于粘包/半包拆分时判断"这条报文一共该有多长",数据没收够时也要返回完整的期望值,
+    // 否则会把半包当完整包切走,导致参数段丢失(表现为服务端返回 NS)。
+    public static Integer getExpectParamLenth(String msg){
+        if(msg.length() < fixedLength){
+            return 0;
+        }
+        Integer length = getParamNums(msg);
+        if(length == 0){
+            return 0;
+        }
+        String msgType = getMsgType(msg);
+        if(msgType.equals("MBDW")||msgType.equals("MJBW")||msgType.equals("VLDW")||msgType.equals("AQDW")||msgType.equals("MCJW")||msgType.equals("MKSW")){ // 绑定类报文,每个参数36字符
+            return length*36;
+        }else if(msgType.equals("MSBW")){ // 设备状态,每个参数4字符
+            return length*4;
+        }
+        return length*12;
+    }
+
+    // 获取参数的总长度(数据未到齐时返回 0,表示当前报文里还取不到参数)
     public static Integer getParamLenth(String msg){
         if(msg.length() < fixedLength){
             return 0;

+ 6 - 1
src/main/java/com/jeesite/modules/utils/XDecoder.java

@@ -226,10 +226,15 @@ public class XDecoder extends ByteToMessageDecoder {
             case "AQRW":
             default: // 默认新报文
                 if(str.length() >= ProtocolParam.fixedLength){ // 大于固定长度
-                    Integer nums = ProtocolParam.getParamLenth(str);
+                    // 必须用"期望长度",不能用 getParamLenth。
+                    // getParamLenth 在参数段还没收齐时返回 0,会算出 tpsize=fixedLength,
+                    // 把半包当完整包切走,参数段丢失后业务侧返回 NS。
+                    Integer nums = ProtocolParam.getExpectParamLenth(str);
                     if(str.length() >= ProtocolParam.fixedLength + nums){
                         tpsize = ProtocolParam.fixedLength + nums;
                     }
+                    // 数据还不够就保持 tpsize=0,由调用方 break 出去,
+                    // 剩余字节留在 tempMsg 里等下一个数据包合并
                 }
                 break;
         }

+ 1 - 0
src/main/resources/config/application.yml

@@ -654,6 +654,7 @@ shiro:
     ${adminPath}/mes/mesProductRecord/work = anon
     ${adminPath}/mes/mesProductRecord/workData = anon
     ${adminPath}/mes/mesProductRecord/winfo = anon
+    ${adminPath}/mes/mesProductRecord/monitor = anon
     ${adminPath}/mes/mesProductRecord/updateQualityByTiming = anon
     ${adminPath}/mes/mesProcessCheckGz/submit = anon
     ${adminPath}/mes/mesProcessCheckRecord/ulist = anon