Commit 73ac8f7ebf170e3f13020170a2a0dca91666f09c

Authored by YunaiV
1 parent 43b38dfc

fix(iot): 修复旧连接清理异常导致设备重连失败

yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/IotMqttProtocol.java
@@ -332,12 +332,12 @@ public class IotMqttProtocol implements IotProtocol { @@ -332,12 +332,12 @@ public class IotMqttProtocol implements IotProtocol {
332 deviceMessageService.sendDeviceMessage(offlineMessage, connectionInfo.getProductKey(), 332 deviceMessageService.sendDeviceMessage(offlineMessage, connectionInfo.getProductKey(),
333 connectionInfo.getDeviceName(), serverId); 333 connectionInfo.getDeviceName(), serverId);
334 } 334 }
335 -  
336 - // 2. 注销连接  
337 - connectionManager.unregisterConnection(endpoint);  
338 } catch (Exception e) { 335 } catch (Exception e) {
339 log.error("[cleanupConnection][清理连接失败,客户端 ID: {},错误: {}]", 336 log.error("[cleanupConnection][清理连接失败,客户端 ID: {},错误: {}]",
340 endpoint.clientIdentifier(), e.getMessage()); 337 endpoint.clientIdentifier(), e.getMessage());
  338 + } finally {
  339 + // 2. 注销连接,避免发送离线消息失败时残留连接
  340 + connectionManager.unregisterConnection(endpoint);
341 } 341 }
342 } 342 }
343 343
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/manager/IotMqttConnectionManager.java
@@ -86,7 +86,13 @@ public class IotMqttConnectionManager { @@ -86,7 +86,13 @@ public class IotMqttConnectionManager {
86 deviceId, getEndpointAddress(oldEndpoint)); 86 deviceId, getEndpointAddress(oldEndpoint));
87 // 先清理映射,再关闭连接(避免旧连接处理器干扰) 87 // 先清理映射,再关闭连接(避免旧连接处理器干扰)
88 connectionMap.remove(oldEndpoint); 88 connectionMap.remove(oldEndpoint);
89 - oldEndpoint.close(); 89 + try {
  90 + if (oldEndpoint.isConnected()) {
  91 + oldEndpoint.close();
  92 + }
  93 + } catch (Exception ignored) {
  94 + // 连接可能已关闭,忽略异常
  95 + }
90 } 96 }
91 97
92 // 注册新连接 98 // 注册新连接
@@ -107,7 +113,8 @@ public class IotMqttConnectionManager { @@ -107,7 +113,8 @@ public class IotMqttConnectionManager {
107 return; 113 return;
108 } 114 }
109 Long deviceId = connectionInfo.getDeviceId(); 115 Long deviceId = connectionInfo.getDeviceId();
110 - deviceEndpointMap.remove(deviceId); 116 + // 仅当 deviceEndpointMap 中的 endpoint 是当前 endpoint 时才移除,避免误删新连接
  117 + deviceEndpointMap.remove(deviceId, endpoint);
111 log.info("[unregisterConnection][注销设备连接,设备 ID: {},连接: {}]", deviceId, getEndpointAddress(endpoint)); 118 log.info("[unregisterConnection][注销设备连接,设备 ID: {},连接: {}]", deviceId, getEndpointAddress(endpoint));
112 } 119 }
113 120
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java
@@ -61,7 +61,11 @@ public class IotTcpConnectionManager { @@ -61,7 +61,11 @@ public class IotTcpConnectionManager {
61 deviceId, oldSocket.remoteAddress()); 61 deviceId, oldSocket.remoteAddress());
62 // 先清理映射,再关闭连接 62 // 先清理映射,再关闭连接
63 connectionMap.remove(oldSocket); 63 connectionMap.remove(oldSocket);
64 - oldSocket.close(); 64 + try {
  65 + oldSocket.close();
  66 + } catch (Exception ignored) {
  67 + // 连接可能已关闭,忽略异常
  68 + }
65 } 69 }
66 70
67 // 注册新连接 71 // 注册新连接
@@ -163,4 +167,4 @@ public class IotTcpConnectionManager { @@ -163,4 +167,4 @@ public class IotTcpConnectionManager {
163 167
164 } 168 }
165 169
166 -}  
167 \ No newline at end of file 170 \ No newline at end of file
  171 +}
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/websocket/manager/IotWebSocketConnectionManager.java
@@ -46,9 +46,13 @@ public class IotWebSocketConnectionManager { @@ -46,9 +46,13 @@ public class IotWebSocketConnectionManager {
46 if (oldSocket != null && oldSocket != socket) { 46 if (oldSocket != null && oldSocket != socket) {
47 log.info("[registerConnection][设备已有其他连接,断开旧连接,设备 ID: {},旧连接: {}]", 47 log.info("[registerConnection][设备已有其他连接,断开旧连接,设备 ID: {},旧连接: {}]",
48 deviceId, oldSocket.remoteAddress()); 48 deviceId, oldSocket.remoteAddress());
49 - oldSocket.close();  
50 - // 清理旧连接的映射 49 + // 先清理映射,再关闭连接
51 connectionMap.remove(oldSocket); 50 connectionMap.remove(oldSocket);
  51 + try {
  52 + oldSocket.close();
  53 + } catch (Exception ignored) {
  54 + // 连接可能已关闭,忽略异常
  55 + }
52 } 56 }
53 57
54 // 注册新连接 58 // 注册新连接