{"record":{"id":"30626d96684cf03f","repo":"YunaiV/ruoyi-vue-pro","slug":"createdecodeparser","errorCode":null,"errorMessage":"[createDecodeParser][解析异常]","messagePattern":"\\[createDecodeParser\\]\\[解析异常\\]","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/delimiter/IotTcpDelimiterFrameCodec.java","lineNumber":58,"sourceCode":"\n    public IotTcpDelimiterFrameCodec(IotTcpConfig.CodecConfig config) {\n        Assert.notBlank(config.getDelimiter(), \"delimiter 不能为空\");\n        this.delimiterBytes = parseDelimiter(config.getDelimiter());\n    }\n\n    @Override\n    public IotTcpCodecTypeEnum getType() {\n        return IotTcpCodecTypeEnum.DELIMITER;\n    }\n\n    @Override\n    public RecordParser createDecodeParser(Handler<Buffer> handler) {\n        RecordParser parser = RecordParser.newDelimited(Buffer.buffer(delimiterBytes));\n        parser.maxRecordSize(MAX_RECORD_SIZE); // 设置最大记录大小，防止 DoS 攻击\n        // 处理完整消息（不包含分隔符）\n        parser.handler(handler);\n        parser.exceptionHandler(ex -> {\n            throw new RuntimeException(\"[createDecodeParser][解析异常]\", ex);\n        });\n        return parser;\n    }\n\n    @Override\n    public Buffer encode(byte[] data) {\n        Buffer buffer = Buffer.buffer();\n        buffer.appendBytes(data);\n        buffer.appendBytes(delimiterBytes);\n        return buffer;\n    }\n\n    /**\n     * 解析分隔符字符串为字节数组\n     * <p>\n     * 支持转义字符：\\n、\\r、\\r\\n、\\t\n     *\n     * @param delimiter 分隔符字符串","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/YunaiV/ruoyi-vue-pro/blob/0418084e222612af2fc1141f566af454f9236ab1/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/delimiter/IotTcpDelimiterFrameCodec.java#L40-L76","documentation":"The Vert.x RecordParser.exceptionHandler for the delimiter-based codec rethrows any parser error as RuntimeException. For this codec the realistic trigger is a record exceeding MAX_RECORD_SIZE (64KB): a device streams data without ever emitting the configured delimiter, so the parser buffers past the cap and fires the exception handler.","triggerScenarios":"Device sends a continuous byte stream that never contains the configured delimiter, crossing 64KB; wrong delimiter configured (device terminates with \\n but config says \\r\\n); a malformed/buggy device flooding garbage; delimiter bytes split across TCP segments in a way that never reassembles (rare with Vert.x).","commonSituations":"Delimiter mismatch between device firmware and gateway config; device firmware forgot to append the delimiter; malicious device; baud-rate/garbage on a serial-to-TCP converter.","solutions":["Confirm the configured delimiter (config.delimiter, supporting \\n \\r \\r\\n \\t or custom) exactly matches the device's frame terminator — capture traffic with Wireshark/tcpdump to verify.","If legitimate frames exceed 64KB, raise MAX_RECORD_SIZE (and ensure memory headroom).","Close or rate-limit the offending connection when the handler fires repeatedly; the exception is thrown on the event loop so add metrics/alerts.","Note: throwing inside exceptionHandler propagates up Vert.x — prefer logging + socket.close() instead of rethrowing to avoid killing the event loop."],"exampleFix":"// before (rethrow can disrupt the Vert.x handler pipeline)\nparser.exceptionHandler(ex -> {\n    throw new RuntimeException(\"[createDecodeParser][解析异常]\", ex);\n});\n\n// after (log + close socket, do not rethrow on event loop)\nparser.exceptionHandler(ex -> {\n    log.error(\"[createDecodeParser][解析异常]\", ex);\n    // signal the owning socket to close\n});","handlingStrategy":"try-catch","validationCode":"// validate the configured delimiter matches observed traffic before relying on the codec\nbyte[] expected = parseDelimiter(config.getDelimiter());\nif (expected.length == 0) {\n    throw new IllegalArgumentException(\"分隔符不能为空\");\n}","typeGuard":null,"tryCatchPattern":"// log + close the offending socket instead of rethrowing on the Vert.x event loop\nparser.exceptionHandler(ex -> {\n    log.error(\"[createDecodeParser][解析异常]\", ex);\n    // signal connection manager to close this socket\n});","preventionTips":["Confirm the delimiter exactly matches the device's frame terminator (capture with tcpdump/Wireshark).","If legitimate frames exceed 64KB, raise MAX_RECORD_SIZE and provision memory.","Do not rethrow inside exceptionHandler — it disrupts the Vert.x pipeline; log and close the socket.","Monitor per-connection parse-error rates to detect misbehaving devices."],"tags":["tcp","codec","vertx","delimiter"],"backgroundTag":null,"analyzedSha":"0418084e222612af2fc1141f566af454f9236ab1","analyzedAt":"2026-08-14T00:56:18.412Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}