From 5dab9622d6bd101ef518278fb8188b83d4f1a2c4 Mon Sep 17 00:00:00 2001 From: lzh Date: Wed, 21 Jan 2026 18:05:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(iot):=20TCP=E6=B6=88=E6=81=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=AE=B9=E9=94=99=E6=94=B9=E8=BF=9B=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E5=BC=82=E5=B8=B8=E6=96=AD=E5=BC=80=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 消息格式无法识别时记录警告并跳过,不断开连接 - 消息解码失败时记录警告并跳过,不断开连接 - 设备不存在时断开连接,其他认证失败只记录日志 - 添加 bytesToHex 工具方法用于调试 Co-Authored-By: Claude Opus 4.5 --- .../tcp/router/IotTcpUpstreamHandler.java | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/viewsh-module-iot/viewsh-module-iot-gateway/src/main/java/com/viewsh/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java b/viewsh-module-iot/viewsh-module-iot-gateway/src/main/java/com/viewsh/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java index 0d3b89f..039612d 100644 --- a/viewsh-module-iot/viewsh-module-iot-gateway/src/main/java/com/viewsh/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java +++ b/viewsh-module-iot/viewsh-module-iot-gateway/src/main/java/com/viewsh/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java @@ -112,17 +112,30 @@ public class IotTcpUpstreamHandler implements Handler { // 2. 获取消息格式类型 String codecType = getMessageCodecType(buffer, socket); + if (codecType == null) { + // 无法识别消息格式,记录警告但不断开连接 + byte[] data = buffer.getBytes(); + String preview = bytesToHex(data, Math.min(32, data.length)); + log.warn("[processMessage][无法识别消息格式,跳过该消息,clientId: {}, 数据前32字节: {}]", + clientId, preview); + return; + } // 3. 解码消息 IotDeviceMessage message; try { message = deviceMessageService.decodeDeviceMessage(buffer.getBytes(), codecType); if (message == null) { - throw new Exception("解码后消息为空"); + // 解码失败(如消息格式错误),记录警告但不断开连接 + log.warn("[processMessage][消息解码失败,跳过该消息,clientId: {}, codecType: {}]", + clientId, codecType); + return; } } catch (Exception e) { - // 消息格式错误时抛出异常,由上层处理连接断开 - throw new Exception("消息解码失败: " + e.getMessage(), e); + // 其他异常也记录警告但不断开连接 + log.warn("[processMessage][消息解码异常,跳过该消息,clientId: {}, codecType: {}, 错误: {}]", + clientId, codecType, e.getMessage()); + return; } // 4. 查找协议处理器 @@ -147,7 +160,7 @@ public class IotTcpUpstreamHandler implements Handler { * 认证结果处理: * - SUCCESS:注册连接,发送上线消息 * - PENDING:等待后续认证步骤(如 JT808 注册后等待鉴权) - * - FAILURE:认证失败,不做处理(协议处理器已发送失败响应) + * - FAILURE:认证失败,如果设备不存在则断开连接,否则只记录日志 * * @param clientId 客户端 ID * @param message 认证消息 @@ -178,9 +191,16 @@ public class IotTcpUpstreamHandler implements Handler { handler.getProtocolType(), result.getMessage()); } else { - // 认证失败:协议处理器已发送失败响应,这里只记录日志 + // 认证失败 + String failureReason = result.getMessage(); log.warn("[handleAuthentication][认证失败,clientId: {}, 协议: {}, 原因: {}]", - clientId, handler.getProtocolType(), result.getMessage()); + clientId, handler.getProtocolType(), failureReason); + + // 如果设备不存在,断开连接 + if (failureReason != null && failureReason.contains("设备不存在")) { + log.warn("[handleAuthentication][设备不存在,断开连接,clientId: {}]", clientId); + socket.close(); + } } } catch (Exception e) { @@ -373,7 +393,7 @@ public class IotTcpUpstreamHandler implements Handler { */ private void cleanupConnection(NetSocket socket) { try { - // 1. 发送离线消息(如果已认证) + // 1. 发送离线消息(如果���认证) IotTcpConnectionManager.ConnectionInfo connectionInfo = connectionManager.getConnectionInfo(socket); if (connectionInfo != null && connectionInfo.isAuthenticated()) { IotDeviceMessage offlineMessage = IotDeviceMessage.buildStateOffline(); @@ -391,4 +411,26 @@ public class IotTcpUpstreamHandler implements Handler { } } + /** + * 字节数组转十六进制字符串 + * + * @param bytes 字节数组 + * @param limit 最大长度 + * @return 十六进制字符串 + */ + private String bytesToHex(byte[] bytes, int limit) { + if (bytes == null || bytes.length == 0) { + return ""; + } + int length = Math.min(bytes.length, limit); + StringBuilder sb = new StringBuilder(length * 2); + for (int i = 0; i < length; i++) { + sb.append(String.format("%02X", bytes[i])); + } + if (bytes.length > limit) { + sb.append("..."); + } + return sb.toString(); + } + }