@pixelhue/event-controller-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +76 -0
  2. package/dist/index.d.ts +17 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +18 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/packages/tcp/ConnectManager.d.ts +66 -0
  7. package/dist/packages/tcp/ConnectManager.d.ts.map +1 -0
  8. package/dist/packages/tcp/ConnectManager.js +176 -0
  9. package/dist/packages/tcp/ConnectManager.js.map +1 -0
  10. package/dist/packages/tcp/QueueManager.d.ts +41 -0
  11. package/dist/packages/tcp/QueueManager.d.ts.map +1 -0
  12. package/dist/packages/tcp/QueueManager.js +102 -0
  13. package/dist/packages/tcp/QueueManager.js.map +1 -0
  14. package/dist/packages/tcp/SocketWrapper.d.ts +106 -0
  15. package/dist/packages/tcp/SocketWrapper.d.ts.map +1 -0
  16. package/dist/packages/tcp/SocketWrapper.js +281 -0
  17. package/dist/packages/tcp/SocketWrapper.js.map +1 -0
  18. package/dist/packages/tcp/constants.d.ts +25 -0
  19. package/dist/packages/tcp/constants.d.ts.map +1 -0
  20. package/dist/packages/tcp/constants.js +27 -0
  21. package/dist/packages/tcp/constants.js.map +1 -0
  22. package/dist/packages/tcp/demo.d.ts +3 -0
  23. package/dist/packages/tcp/demo.d.ts.map +1 -0
  24. package/dist/packages/tcp/demo.js +164 -0
  25. package/dist/packages/tcp/demo.js.map +1 -0
  26. package/dist/packages/tcp/discoveryService.d.ts +42 -0
  27. package/dist/packages/tcp/discoveryService.d.ts.map +1 -0
  28. package/dist/packages/tcp/discoveryService.js +166 -0
  29. package/dist/packages/tcp/discoveryService.js.map +1 -0
  30. package/dist/packages/tcp/protocolHandler.d.ts +64 -0
  31. package/dist/packages/tcp/protocolHandler.d.ts.map +1 -0
  32. package/dist/packages/tcp/protocolHandler.js +96 -0
  33. package/dist/packages/tcp/protocolHandler.js.map +1 -0
  34. package/dist/packages/tcp/tcpWrapper.d.ts +168 -0
  35. package/dist/packages/tcp/tcpWrapper.d.ts.map +1 -0
  36. package/dist/packages/tcp/tcpWrapper.js +472 -0
  37. package/dist/packages/tcp/tcpWrapper.js.map +1 -0
  38. package/dist/packages/tcp/test-build-parse-debug.d.ts +2 -0
  39. package/dist/packages/tcp/test-build-parse-debug.d.ts.map +1 -0
  40. package/dist/packages/tcp/test-build-parse-debug.js +73 -0
  41. package/dist/packages/tcp/test-build-parse-debug.js.map +1 -0
  42. package/dist/packages/tcp/test-packet-split.d.ts +43 -0
  43. package/dist/packages/tcp/test-packet-split.d.ts.map +1 -0
  44. package/dist/packages/tcp/test-packet-split.js +417 -0
  45. package/dist/packages/tcp/test-packet-split.js.map +1 -0
  46. package/dist/packages/tcp/test-protocol-handler.d.ts +6 -0
  47. package/dist/packages/tcp/test-protocol-handler.d.ts.map +1 -0
  48. package/dist/packages/tcp/test-protocol-handler.js +225 -0
  49. package/dist/packages/tcp/test-protocol-handler.js.map +1 -0
  50. package/dist/packages/tcp/test-server.d.ts +54 -0
  51. package/dist/packages/tcp/test-server.d.ts.map +1 -0
  52. package/dist/packages/tcp/test-server.js +412 -0
  53. package/dist/packages/tcp/test-server.js.map +1 -0
  54. package/dist/packages/tcp/types.d.ts +232 -0
  55. package/dist/packages/tcp/types.d.ts.map +1 -0
  56. package/dist/packages/tcp/types.js +13 -0
  57. package/dist/packages/tcp/types.js.map +1 -0
  58. package/dist/packages/tcp/utils.d.ts +14 -0
  59. package/dist/packages/tcp/utils.d.ts.map +1 -0
  60. package/dist/packages/tcp/utils.js +47 -0
  61. package/dist/packages/tcp/utils.js.map +1 -0
  62. package/package.json +82 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcpWrapper.js","sourceRoot":"","sources":["../../../src/packages/tcp/tcpWrapper.ts"],"names":[],"mappings":"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","sourcesContent":["// ALL_CODE_LINE: 450\r\n// AI_CODE_LINE: 40\r\nimport * as net from 'net';\r\nimport type { SocketConnectOptions, HeartbeatResponseChecker } from './types.js';\r\nimport {\r\n\tDEFAULT_AUTO_RECONNECT,\r\n\tDEFAULT_RECONNECT_INTERVAL,\r\n\tDEFAULT_HEARTBEAT_INTERVAL,\r\n\tDEFAULT_HEARTBEAT_TIMEOUT,\r\n\tDEFAULT_MAX_RECONNECT_INTERVAL,\r\n\tDEFAULT_ENABLE_EXPONENTIAL_BACKOFF,\r\n\tDEFAULT_MAX_RECONNECT_ATTEMPTS,\r\n} from './constants.js';\r\n\r\n/**\r\n * tcp连接管理器\r\n * 负责处理 TCP 连接、重连、超时检测等\r\n */\r\nexport class TcpWrapper {\r\n\t/** TCP Socket 实例 */\r\n\tprivate socket: net.Socket | null = null;\r\n\t/** 连接超时定时器 */\r\n\tprivate connectTimeout: NodeJS.Timeout | null = null;\r\n\t/** 重连定时器 */\r\n\tprivate retryConnectTimeout: NodeJS.Timeout | null = null;\r\n\t/** 心跳发送定时器 */\r\n\tprivate heartbeatInterval: NodeJS.Timeout | null = null;\r\n\t/** 心跳响应超时定时器 */\r\n\tprivate heartbeatTimeout: NodeJS.Timeout | null = null;\r\n\r\n\t/** 连接地址 */\r\n\tprivate address: string | null = null;\r\n\t/** 连接端口 */\r\n\tprivate port: number | null = null;\r\n\t/** 连接配置选项 */\r\n\tprivate connectOptions: SocketConnectOptions | null = null;\r\n\r\n\t/** 运行时的连接状态 */\r\n\tprivate connectionActive: boolean = false;\r\n\t/** 是否启用自动重连 */\r\n\tprivate autoReconnect: boolean = false;\r\n\t/** 心跳间隔(毫秒) */\r\n\tprivate heartbeatIntervalMs: number = 5000;\r\n\t/** 心跳超时时间(毫秒) */\r\n\tprivate heartbeatTimeoutMs: number = 5000;\r\n\t/** 是否有待响应的心跳 */\r\n\tprivate pendingHeartbeat: boolean = false;\r\n\t/** 连续心跳超时次数 */\r\n\tprivate heartbeatTimeoutCount: number = 0;\r\n\t/** 心跳响应识别函数 */\r\n\tprivate heartbeatResponseChecker: HeartbeatResponseChecker = (data: Buffer) => {\r\n\t\t// data 是 Buffer 对象,需要转换为字符串比较\r\n\t\t// 心跳响应可能是 \"pong\"(4字节)或 \"pong\\n\"(5字节,带换行符)\r\n\t\tif (data.length === 4) {\r\n\t\t\t// 精确匹配 4 字节的 \"pong\"\r\n\t\t\treturn data.toString('utf8') === 'pong';\r\n\t\t} else if (data.length === 5) {\r\n\t\t\t// 匹配 5 字节的 \"pong\\n\" 或 \"pong\\r\"\r\n\t\t\tconst dataStr = data.toString('utf8');\r\n\t\t\treturn dataStr === 'pong\\n' || dataStr === 'pong\\r';\r\n\t\t} else if (data.length > 4) {\r\n\t\t\t// 检查数据开头是否是 \"pong\"(处理粘包情况:pong + 其他数据)\r\n\t\t\tconst first4Bytes = data.slice(0, 4);\r\n\t\t\tif (first4Bytes.toString('utf8') === 'pong') {\r\n\t\t\t\t// 检查第5个字节是否是换行符或数据结束\r\n\t\t\t\tif (data.length === 5 || data[4] === 0x0a || data[4] === 0x0d) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t};\r\n\t/** 最大重连次数,0 表示无限制 */\r\n\tprivate maxReconnectAttempts: number = 0;\r\n\t/** 是否启用指数退避 */\r\n\tprivate enableExponentialBackoff: boolean = true;\r\n\t/** 指数退避的最大间隔(毫秒) */\r\n\tprivate maxReconnectInterval: number = 60000;\r\n\t/** 当前重连次数 */\r\n\tprivate reconnectAttempts: number = 0;\r\n\t/** 基础重连间隔(毫秒) */\r\n\tprivate reconnectInterval: number = 5000;\r\n\t/** 连接开始时间(用于计算握手时间) */\r\n\tprivate connectStartTime: number = 0;\r\n\t/** 握手超时尝试次数 */\r\n\tprivate handshakeTimeoutAttempts: number = 0;\r\n\t/** 最大握手超时尝试次数 */\r\n\tprivate readonly maxHandshakeTimeoutAttempts: number = 3;\r\n\t/** 基础握手重试间隔(毫秒) */\r\n\tprivate readonly baseHandshakeRetryInterval: number = 1000;\r\n\t/** 最大握手重试间隔(毫秒) */\r\n\tprivate readonly maxHandshakeRetryInterval: number = 3000;\r\n\r\n\t/** 连接成功回调 */\r\n\tprivate onConnected?: () => void;\r\n\t/** 连接断开回调(自动重连时会触发) */\r\n\tprivate onDisconnected?: () => void;\r\n\t/** 接收数据回调 */\r\n\tprivate onData?: (data: Buffer) => void;\r\n\t/** 错误回调 */\r\n\tprivate onError?: (error: Error) => void;\r\n\t/** 连接关闭回调(手动断开或重连失败时触发) */\r\n\tprivate onClose?: () => void;\r\n\r\n\tconstructor() {}\r\n\r\n\t/**\r\n\t * 设置 Socket 事件监听\r\n\t */\r\n\tprivate setupSocketEvents(): void {\r\n\t\tif (!this.socket) return;\r\n\r\n\t\tthis.socket.on('connect', () => {\r\n\t\t\tthis.clearConnectTimeout();\r\n\r\n\t\t\t// 计算TCP握手时间\r\n\t\t\tif (this.connectStartTime > 0) {\r\n\t\t\t\tthis.connectStartTime = 0; // 重置时间戳\r\n\t\t\t}\r\n\r\n\t\t\t// 连接成功,重置所有计数器\r\n\t\t\tthis.reconnectAttempts = 0;\r\n\t\t\tthis.heartbeatTimeoutCount = 0;\r\n\t\t\tthis.handshakeTimeoutAttempts = 0; // 重置握手超时计数\r\n\r\n\t\t\tthis.startHeartbeat();\r\n\t\t\t// 触发连接成功回调\r\n\t\t\tthis.onConnected?.();\r\n\t\t});\r\n\r\n\t\tthis.socket.on('data', (data: Buffer) => {\r\n\t\t\t// 检查是否是心跳响应\r\n\t\t\tif (this.heartbeatResponseChecker?.(data)) {\r\n\t\t\t\tthis.clearHeartbeatTimeout();\r\n\t\t\t\tthis.pendingHeartbeat = false;\r\n\t\t\t\tthis.heartbeatTimeoutCount = 0; // 重置超时计数\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.onData?.(data);\r\n\t\t});\r\n\r\n\t\tthis.socket.on('close', (_hadError: boolean) => {\r\n\t\t\tthis.clearConnectTimeout();\r\n\t\t\tthis.stopHeartbeat();\r\n\t\t\tthis.cleanup();\r\n\r\n\t\t\tif (this.connectionActive && this.autoReconnect) {\r\n\t\t\t\tthis.onDisconnected?.();\r\n\t\t\t\tthis.triggerRetryConnection();\r\n\t\t\t} else {\r\n\t\t\t\tthis.connectionActive = false;\r\n\t\t\t\tthis.onClose?.();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.socket.on('error', (error: Error) => {\r\n\t\t\tthis.clearConnectTimeout();\r\n\t\t\tthis.onError?.(error);\r\n\r\n\t\t\tif (this.connectionActive && this.autoReconnect && this.socket?.destroyed) {\r\n\t\t\t\tthis.triggerRetryConnection();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tthis.socket.on('timeout', () => {\r\n\t\t\tthis.clearConnectTimeout();\r\n\t\t\tthis.socket?.destroy();\r\n\t\t\tthis.onError?.(new Error('Connection timeout'));\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * 检查是否达到最大重连次数\r\n\t */\r\n\tprivate hasReachedMaxAttempts(): boolean {\r\n\t\treturn this.maxReconnectAttempts > 0 && this.reconnectAttempts >= this.maxReconnectAttempts;\r\n\t}\r\n\r\n\t/**\r\n\t * 计算重连间隔(考虑指数退避)\r\n\t */\r\n\tprivate calculateReconnectInterval(): number {\r\n\t\t// 指数退避:interval = baseInterval * 2^attempts,但不超过 maxReconnectInterval\r\n\t\treturn !this.enableExponentialBackoff\r\n\t\t\t? this.reconnectInterval\r\n\t\t\t: Math.min(this.reconnectInterval * Math.pow(2, this.reconnectAttempts), this.maxReconnectInterval);\r\n\t}\r\n\r\n\t/**\r\n\t * 计算握手超时重试间隔(使用指数退避)\r\n\t */\r\n\tprivate calculateHandshakeRetryInterval(): number {\r\n\t\t// 指数退避:interval = baseInterval * 2^attempts,但不超过 maxHandshakeRetryInterval\r\n\t\t// attempts 从 0 开始,所以第一次重试是 baseInterval * 2^0 = baseInterval\r\n\t\treturn Math.min(\r\n\t\t\tthis.baseHandshakeRetryInterval * Math.pow(2, this.handshakeTimeoutAttempts - 1),\r\n\t\t\tthis.maxHandshakeRetryInterval\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * 触发重连\r\n\t */\r\n\tprivate triggerRetryConnection(): void {\r\n\t\tif (!this.connectionActive || !this.autoReconnect) return;\r\n\r\n\t\t// 检查最大重连次数\r\n\t\tif (this.hasReachedMaxAttempts()) {\r\n\t\t\tthis.connectionActive = false;\r\n\t\t\tthis.onClose?.();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// 如果已有重连定时器,不重复设置\r\n\t\tif (this.retryConnectTimeout) return;\r\n\r\n\t\tconst interval = this.calculateReconnectInterval();\r\n\t\tthis.retryConnectTimeout = setTimeout(() => {\r\n\t\t\tthis.retryConnection();\r\n\t\t}, interval);\r\n\t}\r\n\r\n\t/**\r\n\t * 执行重连\r\n\t */\r\n\tprivate retryConnection(): void {\r\n\t\tthis.clearRetryConnectTimeout();\r\n\r\n\t\tif (!this.connectionActive) return;\r\n\t\tif (this.isConnected()) return;\r\n\r\n\t\t// 再次检查最大重连次数(防止在等待期间达到上限)||如果连接信息缺失,停止重连,避免无限递归\r\n\t\tif (this.hasReachedMaxAttempts() || !this.connectOptions || !this.address || !this.port) {\r\n\t\t\tthis.connectionActive = false;\r\n\t\t\tthis.onClose?.();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// 增加重连计数\r\n\t\tthis.reconnectAttempts++;\r\n\r\n\t\ttry {\r\n\t\t\tthis.connect(this.address!, this.port!, this.connectOptions!);\r\n\t\t} catch (error) {\r\n\t\t\tthis.onError?.(error as Error);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 启动心跳\r\n\t */\r\n\tprivate startHeartbeat(): void {\r\n\t\tif (this.heartbeatInterval) return;\r\n\r\n\t\t// 立即发送一次心跳\r\n\t\tthis.sendHeartbeat();\r\n\r\n\t\t// 设置定时发送心跳\r\n\t\tthis.heartbeatInterval = setInterval(() => {\r\n\t\t\tthis.sendHeartbeat();\r\n\t\t}, this.heartbeatIntervalMs);\r\n\t}\r\n\r\n\t/**\r\n\t * 停止心跳\r\n\t */\r\n\tprivate stopHeartbeat(): void {\r\n\t\tif (this.heartbeatInterval) {\r\n\t\t\tclearInterval(this.heartbeatInterval);\r\n\t\t\tthis.heartbeatInterval = null;\r\n\t\t}\r\n\t\tthis.clearHeartbeatTimeout();\r\n\t\tthis.pendingHeartbeat = false;\r\n\t\tthis.heartbeatTimeoutCount = 0; // 重置超时计数\r\n\t}\r\n\r\n\t/**\r\n\t * 发送心跳包\r\n\t */\r\n\tprivate sendHeartbeat(): void {\r\n\t\tif (!this.socket?.writable || this.socket.destroyed) return;\r\n\r\n\t\ttry {\r\n\t\t\tthis.socket.write('ping');\r\n\t\t\tthis.pendingHeartbeat = true;\r\n\r\n\t\t\t// 设置心跳响应超时\r\n\t\t\tthis.clearHeartbeatTimeout();\r\n\t\t\tthis.heartbeatTimeout = setTimeout(() => {\r\n\t\t\t\tif (this.pendingHeartbeat) {\r\n\t\t\t\t\tthis.heartbeatTimeoutCount++;\r\n\r\n\t\t\t\t\t// 只有连续2次心跳超时才清理socket\r\n\t\t\t\t\tif (this.heartbeatTimeoutCount >= 2) {\r\n\t\t\t\t\t\tthis.connectionActive = false;\r\n\t\t\t\t\t\tthis.onDisconnected?.();\r\n\t\t\t\t\t\tthis.socket?.destroy();\r\n\r\n\t\t\t\t\t\t// 如果启用了自动重连,触发重连\r\n\t\t\t\t\t\tif (this.autoReconnect) {\r\n\t\t\t\t\t\t\tthis.connectionActive = true;\r\n\t\t\t\t\t\t\tthis.triggerRetryConnection();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}, this.heartbeatTimeoutMs);\r\n\t\t} catch (error) {\r\n\t\t\tthis.onError?.(error as Error);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 清除心跳响应超时定时器\r\n\t */\r\n\tprivate clearHeartbeatTimeout(): void {\r\n\t\tif (this.heartbeatTimeout) {\r\n\t\t\tclearTimeout(this.heartbeatTimeout);\r\n\t\t\tthis.heartbeatTimeout = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 设置连接超时\r\n\t */\r\n\tprivate setConnectTimeout(): void {\r\n\t\tthis.clearConnectTimeout();\r\n\t\tthis.connectTimeout = setTimeout(() => {\r\n\t\t\tif (this.socket && !this.socket.destroyed) {\r\n\t\t\t\tthis.handshakeTimeoutAttempts++;\r\n\r\n\t\t\t\t// 如果未达到最大尝试次数,重试连接\r\n\t\t\t\tif (this.handshakeTimeoutAttempts < this.maxHandshakeTimeoutAttempts) {\r\n\t\t\t\t\t// 清理当前socket\r\n\t\t\t\t\tthis.socket.destroy();\r\n\t\t\t\t\tthis.socket = null;\r\n\r\n\t\t\t\t\t// 计算重试延迟(使用指数退避)\r\n\t\t\t\t\tconst retryDelay = this.calculateHandshakeRetryInterval();\r\n\r\n\t\t\t\t\t// 重新尝试连接\r\n\t\t\t\t\tif (this.address && this.port && this.connectOptions) {\r\n\t\t\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\t\t\tif (this.connectionActive && !this.isConnected()) {\r\n\t\t\t\t\t\t\t\ttry {\r\n\t\t\t\t\t\t\t\t\t// 重新创建连接\r\n\t\t\t\t\t\t\t\t\tthis.socket = net.createConnection({\r\n\t\t\t\t\t\t\t\t\t\thost: this.address!,\r\n\t\t\t\t\t\t\t\t\t\tport: this.port!,\r\n\t\t\t\t\t\t\t\t\t\tkeepAlive: true,\r\n\t\t\t\t\t\t\t\t\t\tkeepAliveInitialDelay: 1000,\r\n\t\t\t\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\t\t\t\t\t// 重新设置超时和事件\r\n\t\t\t\t\t\t\t\t\tthis.setConnectTimeout();\r\n\t\t\t\t\t\t\t\t\tthis.setupSocketEvents();\r\n\t\t\t\t\t\t\t\t} catch (error) {\r\n\t\t\t\t\t\t\t\t\tthis.onError?.(error as Error);\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}, retryDelay);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// 超过最大尝试次数,断开连接\r\n\t\t\t\t\tthis.connectionActive = false;\r\n\t\t\t\t\tthis.socket.destroy();\r\n\t\t\t\t\tthis.onError?.(new Error(`Connection timeout after ${this.maxHandshakeTimeoutAttempts} attempts`));\r\n\t\t\t\t\tthis.onClose?.();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}, 1000);\r\n\t}\r\n\r\n\t/**\r\n\t * 清除连接超时定时器\r\n\t */\r\n\tprivate clearConnectTimeout(): void {\r\n\t\tif (this.connectTimeout) {\r\n\t\t\tclearTimeout(this.connectTimeout);\r\n\t\t\tthis.connectTimeout = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 清除重连定时器\r\n\t */\r\n\tprivate clearRetryConnectTimeout(): void {\r\n\t\tif (this.retryConnectTimeout) {\r\n\t\t\tclearTimeout(this.retryConnectTimeout);\r\n\t\t\tthis.retryConnectTimeout = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 清理资源\r\n\t */\r\n\tprivate cleanup(): void {\r\n\t\tthis.clearConnectTimeout();\r\n\t}\r\n\r\n\t/**\r\n\t * 设置事件回调\r\n\t */\r\n\tsetEventHandlers(handlers: {\r\n\t\tonConnected?: () => void;\r\n\t\tonDisconnected?: () => void;\r\n\t\tonData?: (data: Buffer) => void;\r\n\t\tonError?: (error: Error) => void;\r\n\t\tonClose?: () => void;\r\n\t}): void {\r\n\t\tthis.onConnected = handlers.onConnected;\r\n\t\tthis.onDisconnected = handlers.onDisconnected;\r\n\t\tthis.onData = handlers.onData;\r\n\t\tthis.onError = handlers.onError;\r\n\t\tthis.onClose = handlers.onClose;\r\n\t}\r\n\r\n\t/**\r\n\t * 连接\r\n\t */\r\n\tconnect(host: string, port: number, options: SocketConnectOptions): void {\r\n\t\tif (!host || !port) {\r\n\t\t\tthis.onError?.(new Error(`Invalid connection parameters: host=${host}, port=${port}`));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// 保存连接信息用于重连\r\n\t\tthis.address = host;\r\n\t\tthis.port = port;\r\n\t\tthis.connectOptions = { ...options };\r\n\t\tthis.connectionActive = true;\r\n\r\n\t\t// 配置重连和心跳\r\n\t\tthis.autoReconnect = options.autoReconnect ?? DEFAULT_AUTO_RECONNECT;\r\n\t\tthis.reconnectInterval = options.reconnectInterval ?? DEFAULT_RECONNECT_INTERVAL;\r\n\t\tthis.heartbeatIntervalMs = options.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;\r\n\t\tthis.heartbeatTimeoutMs = options.heartbeatTimeout ?? DEFAULT_HEARTBEAT_TIMEOUT;\r\n\t\tthis.maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\r\n\t\tthis.enableExponentialBackoff = options.enableExponentialBackoff ?? DEFAULT_ENABLE_EXPONENTIAL_BACKOFF;\r\n\t\tthis.maxReconnectInterval = options.maxReconnectInterval ?? DEFAULT_MAX_RECONNECT_INTERVAL;\r\n\r\n\t\t// 重置重连计数器和握手超时计数器(新连接时)\r\n\t\tthis.reconnectAttempts = 0;\r\n\t\tthis.handshakeTimeoutAttempts = 0;\r\n\r\n\t\t// 如果已有 socket,先清理\r\n\t\tif (this.socket) {\r\n\t\t\tthis.socket.removeAllListeners();\r\n\t\t\tif (!this.socket.destroyed) {\r\n\t\t\t\tthis.socket.destroy();\r\n\t\t\t}\r\n\t\t\tthis.socket = null;\r\n\t\t}\r\n\r\n\t\t// 记录连接开始时间(用于计算握手时间)\r\n\t\tthis.connectStartTime = Date.now();\r\n\r\n\t\t// 创建 TCP 连接\r\n\t\tthis.socket = net.createConnection({\r\n\t\t\thost,\r\n\t\t\tport,\r\n\t\t\tkeepAlive: true,\r\n\t\t\tkeepAliveInitialDelay: 1000, // TCP keepalive 初始延迟时间(毫秒)\r\n\t\t});\r\n\r\n\t\t// 设置连接超时( 1000ms)\r\n\t\tthis.setConnectTimeout();\r\n\r\n\t\t// 绑定事件\r\n\t\tthis.setupSocketEvents();\r\n\t}\r\n\r\n\t/**\r\n\t * 断开连接\r\n\t */\r\n\tdisconnect(): void {\r\n\t\tthis.connectionActive = false;\r\n\t\tthis.clearConnectTimeout();\r\n\t\tthis.clearRetryConnectTimeout();\r\n\t\tthis.stopHeartbeat();\r\n\r\n\t\tif (this.socket) {\r\n\t\t\tif (this.socket.writable) {\r\n\t\t\t\tthis.socket.end();\r\n\t\t\t} else {\r\n\t\t\t\tthis.socket.destroy();\r\n\t\t\t}\r\n\t\t\tthis.socket = null;\r\n\t\t}\r\n\r\n\t\t// 重置连接信息和所有计数器\r\n\t\tthis.address = null;\r\n\t\tthis.port = null;\r\n\t\tthis.connectOptions = null;\r\n\t\tthis.reconnectAttempts = 0;\r\n\t\tthis.handshakeTimeoutAttempts = 0;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取 Socket 实例\r\n\t */\r\n\tgetSocket(): net.Socket | null {\r\n\t\treturn this.socket;\r\n\t}\r\n\r\n\t/**\r\n\t * 检查是否已连接\r\n\t */\r\n\tisConnected(): boolean {\r\n\t\treturn this.socket !== null && !this.socket.destroyed && this.socket.writable;\r\n\t}\r\n\r\n\t/**\r\n\t * 设置心跳响应识别函数\r\n\t */\r\n\tsetHeartbeatResponseChecker(checker: HeartbeatResponseChecker): void {\r\n\t\tthis.heartbeatResponseChecker = checker || ((data: Buffer) => data.toString() === 'pong');\r\n\t}\r\n\r\n\t/**\r\n\t * 获取当前连接地址\r\n\t */\r\n\tgetAddress(): string | null {\r\n\t\treturn this.address;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取当前连接端口\r\n\t */\r\n\tgetPort(): number | null {\r\n\t\treturn this.port;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取当前重连次数\r\n\t */\r\n\tgetReconnectAttempts(): number {\r\n\t\treturn this.reconnectAttempts;\r\n\t}\r\n}\r\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-build-parse-debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-build-parse-debug.d.ts","sourceRoot":"","sources":["../../../src/packages/tcp/test-build-parse-debug.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ // ALL_CODE_LINE: 80
2
+ // AI_CODE_LINE: 80
3
+ /**
4
+ * 调试构建和解析流程,检查数据格式是否正确
5
+ */
6
+ import { ProtocolHandler } from './protocolHandler.js';
7
+ const handler = new ProtocolHandler();
8
+ // 测试数据
9
+ const testData = {
10
+ row: 2,
11
+ column: 3,
12
+ page: 0,
13
+ type: 0,
14
+ };
15
+ const testHeader = {
16
+ seq: 1,
17
+ sn: 'TEST001',
18
+ source: 'device',
19
+ };
20
+ console.log('='.repeat(80));
21
+ console.log('构建和解析流程调试');
22
+ console.log('='.repeat(80));
23
+ console.log('');
24
+ // 1. 构建数据包
25
+ console.log('1. 构建数据包');
26
+ console.log(' 原始数据:', JSON.stringify(testData));
27
+ console.log(' 原始头部:', JSON.stringify(testHeader));
28
+ const packet = handler.build(testData, testHeader);
29
+ console.log(` 数据包大小: ${packet.length} 字节`);
30
+ console.log(` Hex (前64字节): ${packet.toString('hex').substring(0, 128)}`);
31
+ console.log('');
32
+ // 2. 解析数据包
33
+ console.log('2. 解析数据包');
34
+ const result = handler.parse(packet);
35
+ console.log(' 解析结果:');
36
+ console.log(' - data:', JSON.stringify(result.data));
37
+ console.log(' - header:', JSON.stringify(result.header));
38
+ console.log(' - requestId:', result.requestId);
39
+ console.log(' - isResponse:', result.isResponse);
40
+ console.log('');
41
+ // 3. 检查数据格式
42
+ console.log('3. 数据格式检查');
43
+ console.log(' data 类型:', typeof result.data);
44
+ console.log(' data 是否为对象:', typeof result.data === 'object' && result.data !== null);
45
+ console.log(' header 类型:', typeof result.header);
46
+ console.log(' header 是否为对象:', typeof result.header === 'object' && result.header !== null);
47
+ console.log('');
48
+ // 4. 验证数据一致性
49
+ console.log('4. 数据一致性验证');
50
+ const dataMatch = JSON.stringify(result.data) === JSON.stringify(testData);
51
+ const headerMatch = JSON.stringify(result.header) === JSON.stringify(testHeader);
52
+ console.log(' data 匹配:', dataMatch ? '✅' : '❌');
53
+ console.log(' header 匹配:', headerMatch ? '✅' : '❌');
54
+ if (!dataMatch) {
55
+ console.log(' 原始 data:', JSON.stringify(testData));
56
+ console.log(' 解析 data:', JSON.stringify(result.data));
57
+ }
58
+ if (!headerMatch) {
59
+ console.log(' 原始 header:', JSON.stringify(testHeader));
60
+ console.log(' 解析 header:', JSON.stringify(result.header));
61
+ }
62
+ console.log('');
63
+ // 5. 检查是否是 Buffer 对象
64
+ console.log('5. 检查是否是 Buffer 对象');
65
+ console.log(' data 是 Buffer:', Buffer.isBuffer(result.data));
66
+ console.log(' header 是 Buffer:', Buffer.isBuffer(result.header));
67
+ console.log(' data 是 ArrayBuffer:', result.data instanceof ArrayBuffer);
68
+ console.log(' header 是 ArrayBuffer:', result.header instanceof ArrayBuffer);
69
+ console.log('');
70
+ console.log('='.repeat(80));
71
+ console.log('调试完成');
72
+ console.log('='.repeat(80));
73
+ //# sourceMappingURL=test-build-parse-debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-build-parse-debug.js","sourceRoot":"","sources":["../../../src/packages/tcp/test-build-parse-debug.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,mBAAmB;AAEnB;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;AAEtC,OAAO;AACP,MAAM,QAAQ,GAAG;IAChB,GAAG,EAAE,CAAC;IACN,MAAM,EAAE,CAAC;IACT,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;CACP,CAAC;AAEF,MAAM,UAAU,GAAG;IAClB,GAAG,EAAE,CAAC;IACN,EAAE,EAAE,SAAS;IACb,MAAM,EAAE,QAAQ;CAChB,CAAC;AAEF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,WAAW;AACX,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACxB,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClD,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;AACpD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACnD,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7C,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AAC3E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,WAAW;AACX,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACxB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACrC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACxB,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3D,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;AACjD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;AACnD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,YAAY;AACZ,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACzB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/C,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACvF,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;AACnD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AAC7F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,aAAa;AACb,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACjF,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAClD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AACtD,IAAI,CAAC,SAAS,EAAE,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACzD,CAAC;AACD,IAAI,CAAC,WAAW,EAAE,CAAC;IAClB,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7D,CAAC;AACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,qBAAqB;AACrB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAClC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC/D,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACnE,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,IAAI,YAAY,WAAW,CAAC,CAAC;AAC1E,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,MAAM,YAAY,WAAW,CAAC,CAAC;AAC9E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAEhB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACpB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC","sourcesContent":["// ALL_CODE_LINE: 80\r\n// AI_CODE_LINE: 80\r\n\r\n/**\r\n * 调试构建和解析流程,检查数据格式是否正确\r\n */\r\n\r\nimport { ProtocolHandler } from './protocolHandler.js';\r\n\r\nconst handler = new ProtocolHandler();\r\n\r\n// 测试数据\r\nconst testData = {\r\n\trow: 2,\r\n\tcolumn: 3,\r\n\tpage: 0,\r\n\ttype: 0,\r\n};\r\n\r\nconst testHeader = {\r\n\tseq: 1,\r\n\tsn: 'TEST001',\r\n\tsource: 'device',\r\n};\r\n\r\nconsole.log('='.repeat(80));\r\nconsole.log('构建和解析流程调试');\r\nconsole.log('='.repeat(80));\r\nconsole.log('');\r\n\r\n// 1. 构建数据包\r\nconsole.log('1. 构建数据包');\r\nconsole.log(' 原始数据:', JSON.stringify(testData));\r\nconsole.log(' 原始头部:', JSON.stringify(testHeader));\r\nconst packet = handler.build(testData, testHeader);\r\nconsole.log(` 数据包大小: ${packet.length} 字节`);\r\nconsole.log(` Hex (前64字节): ${packet.toString('hex').substring(0, 128)}`);\r\nconsole.log('');\r\n\r\n// 2. 解析数据包\r\nconsole.log('2. 解析数据包');\r\nconst result = handler.parse(packet);\r\nconsole.log(' 解析结果:');\r\nconsole.log(' - data:', JSON.stringify(result.data));\r\nconsole.log(' - header:', JSON.stringify(result.header));\r\nconsole.log(' - requestId:', result.requestId);\r\nconsole.log(' - isResponse:', result.isResponse);\r\nconsole.log('');\r\n\r\n// 3. 检查数据格式\r\nconsole.log('3. 数据格式检查');\r\nconsole.log(' data 类型:', typeof result.data);\r\nconsole.log(' data 是否为对象:', typeof result.data === 'object' && result.data !== null);\r\nconsole.log(' header 类型:', typeof result.header);\r\nconsole.log(' header 是否为对象:', typeof result.header === 'object' && result.header !== null);\r\nconsole.log('');\r\n\r\n// 4. 验证数据一致性\r\nconsole.log('4. 数据一致性验证');\r\nconst dataMatch = JSON.stringify(result.data) === JSON.stringify(testData);\r\nconst headerMatch = JSON.stringify(result.header) === JSON.stringify(testHeader);\r\nconsole.log(' data 匹配:', dataMatch ? '✅' : '❌');\r\nconsole.log(' header 匹配:', headerMatch ? '✅' : '❌');\r\nif (!dataMatch) {\r\n\tconsole.log(' 原始 data:', JSON.stringify(testData));\r\n\tconsole.log(' 解析 data:', JSON.stringify(result.data));\r\n}\r\nif (!headerMatch) {\r\n\tconsole.log(' 原始 header:', JSON.stringify(testHeader));\r\n\tconsole.log(' 解析 header:', JSON.stringify(result.header));\r\n}\r\nconsole.log('');\r\n\r\n// 5. 检查是否是 Buffer 对象\r\nconsole.log('5. 检查是否是 Buffer 对象');\r\nconsole.log(' data 是 Buffer:', Buffer.isBuffer(result.data));\r\nconsole.log(' header 是 Buffer:', Buffer.isBuffer(result.header));\r\nconsole.log(' data 是 ArrayBuffer:', result.data instanceof ArrayBuffer);\r\nconsole.log(' header 是 ArrayBuffer:', result.header instanceof ArrayBuffer);\r\nconsole.log('');\r\n\r\nconsole.log('='.repeat(80));\r\nconsole.log('调试完成');\r\nconsole.log('='.repeat(80));\r\n"]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 半包和粘包测试
3
+ *
4
+ * 测试场景:
5
+ * 1. 半包测试:将一个完整的数据包分成多个部分发送
6
+ * 2. 粘包测试:将多个完整的数据包合并在一起发送
7
+ * 3. 混合场景:半包 + 粘包
8
+ *
9
+ * 使用方式:
10
+ * 1. 先启动测试服务器: npm run test-server
11
+ * 2. 运行此测试: npx tsx src/packages/tcp/test-packet-split.ts
12
+ */
13
+ declare class PacketSplitTester {
14
+ private protocolHandler;
15
+ private testResults;
16
+ constructor();
17
+ /**
18
+ * 创建测试数据包
19
+ */
20
+ private createTestPacket;
21
+ /**
22
+ * 测试场景1:半包测试 - 将一个完整包分成多段发送
23
+ */
24
+ private testHalfPacket;
25
+ /**
26
+ * 测试场景2:粘包测试 - 将多个完整包合并发送
27
+ */
28
+ private testStickyPacket;
29
+ /**
30
+ * 测试场景3:混合场景 - 半包 + 粘包
31
+ */
32
+ private testMixedPacket;
33
+ /**
34
+ * 测试场景4:大量粘包测试
35
+ */
36
+ private testManyStickyPackets;
37
+ /**
38
+ * 运行所有测试
39
+ */
40
+ runAllTests(port?: number): Promise<void>;
41
+ }
42
+ export { PacketSplitTester };
43
+ //# sourceMappingURL=test-packet-split.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-packet-split.d.ts","sourceRoot":"","sources":["../../../src/packages/tcp/test-packet-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAaH,cAAM,iBAAiB;IACtB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAoB;;IAMvC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;YACW,cAAc;IAgH5B;;OAEG;YACW,gBAAgB;IAkF9B;;OAEG;YACW,eAAe;IA8F7B;;OAEG;YACW,qBAAqB;IAsEnC;;OAEG;IACG,WAAW,CAAC,IAAI,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAiDrD;AAoBD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,417 @@
1
+ /**
2
+ * 半包和粘包测试
3
+ *
4
+ * 测试场景:
5
+ * 1. 半包测试:将一个完整的数据包分成多个部分发送
6
+ * 2. 粘包测试:将多个完整的数据包合并在一起发送
7
+ * 3. 混合场景:半包 + 粘包
8
+ *
9
+ * 使用方式:
10
+ * 1. 先启动测试服务器: npm run test-server
11
+ * 2. 运行此测试: npx tsx src/packages/tcp/test-packet-split.ts
12
+ */
13
+ import * as net from 'net';
14
+ import { ProtocolHandler } from './protocolHandler.js';
15
+ class PacketSplitTester {
16
+ protocolHandler;
17
+ testResults = [];
18
+ constructor() {
19
+ this.protocolHandler = new ProtocolHandler();
20
+ }
21
+ /**
22
+ * 创建测试数据包
23
+ */
24
+ createTestPacket(index) {
25
+ const data = {
26
+ message: `Test packet ${index}`,
27
+ timestamp: Date.now(),
28
+ index: index,
29
+ };
30
+ const header = {
31
+ seq: index,
32
+ sn: `test-${index}`,
33
+ source: 'test-client',
34
+ };
35
+ return this.protocolHandler.build(data, header);
36
+ }
37
+ /**
38
+ * 测试场景1:半包测试 - 将一个完整包分成多段发送
39
+ */
40
+ async testHalfPacket(port) {
41
+ return new Promise((resolve) => {
42
+ const client = new net.Socket();
43
+ // 禁用 Nagle 算法,确保小段数据立即发送
44
+ client.setNoDelay(true);
45
+ let receivedPackets = 0;
46
+ const expectedPackets = 1;
47
+ const testPacket = this.createTestPacket(1);
48
+ const splitPoints = [10, 30, 50, testPacket.length]; // 分段点
49
+ client.connect(port, '127.0.0.1', () => {
50
+ console.log('📦 [半包测试] 连接成功,开始发送分段数据包...');
51
+ console.log(` 完整包大小: ${testPacket.length} 字节`);
52
+ console.log(` 分段点: ${splitPoints.join(', ')}`);
53
+ // 分段发送,每段之间添加延迟
54
+ let lastIndex = 0;
55
+ const sendNextChunk = (i) => {
56
+ if (i >= splitPoints.length) {
57
+ console.log(` ✅ 所有分段已发送完成`);
58
+ return;
59
+ }
60
+ const end = splitPoints[i];
61
+ const chunk = testPacket.slice(lastIndex, end);
62
+ console.log(` 发送第 ${i + 1} 段: ${chunk.length} 字节 (${lastIndex}-${end})`);
63
+ // 使用回调确保数据真正发送后再发送下一段
64
+ client.write(chunk, (err) => {
65
+ if (err) {
66
+ console.error(` ❌ 发送第 ${i + 1} 段失败:`, err.message);
67
+ }
68
+ });
69
+ lastIndex = end;
70
+ // 每段之间延迟,模拟网络延迟
71
+ if (i < splitPoints.length - 1) {
72
+ setTimeout(() => {
73
+ sendNextChunk(i + 1);
74
+ }, 100); // 增加到 100ms 延迟,确保分段真正分开
75
+ }
76
+ else {
77
+ console.log(` ✅ 所有分段已发送完成`);
78
+ }
79
+ };
80
+ // 开始发送第一段
81
+ sendNextChunk(0);
82
+ });
83
+ const receiveBuffer = [];
84
+ client.on('data', (data) => {
85
+ console.log(` 📥 接收到原始数据: ${data.length} 字节`);
86
+ receiveBuffer.push(data);
87
+ const fullBuffer = Buffer.concat(receiveBuffer);
88
+ console.log(` 📦 当前缓冲区大小: ${fullBuffer.length} 字节`);
89
+ // 尝试提取完整包
90
+ const { packets, remaining } = this.protocolHandler.extractAllCompletePackets(fullBuffer);
91
+ if (packets.length > 0) {
92
+ receivedPackets += packets.length;
93
+ console.log(` ✅ 接收到 ${packets.length} 个完整包`);
94
+ // 验证数据
95
+ for (const packet of packets) {
96
+ try {
97
+ const parseResult = this.protocolHandler.parse(packet);
98
+ console.log(` ✅ 解析成功: ${JSON.stringify(parseResult.data)}`);
99
+ }
100
+ catch (error) {
101
+ console.error(` ❌ 解析失败:`, error);
102
+ }
103
+ }
104
+ }
105
+ else {
106
+ console.log(` ⏳ 缓冲区中暂无完整包,剩余: ${remaining?.length || 0} 字节`);
107
+ }
108
+ // 更新接收缓冲区
109
+ receiveBuffer.length = 0;
110
+ if (remaining) {
111
+ receiveBuffer.push(remaining);
112
+ }
113
+ });
114
+ client.on('error', (error) => {
115
+ console.error(` ❌ 连接错误:`, error.message);
116
+ resolve({
117
+ name: '半包测试',
118
+ passed: false,
119
+ error: error.message,
120
+ receivedPackets: 0,
121
+ expectedPackets,
122
+ });
123
+ });
124
+ // 等待接收完成(增加等待时间,因为分段发送需要时间)
125
+ setTimeout(() => {
126
+ client.destroy();
127
+ const passed = receivedPackets === expectedPackets;
128
+ console.log(` ${passed ? '✅' : '❌'} 测试结果: 期望 ${expectedPackets} 个包,实际收到 ${receivedPackets} 个包\n`);
129
+ resolve({
130
+ name: '半包测试',
131
+ passed,
132
+ receivedPackets,
133
+ expectedPackets,
134
+ });
135
+ }, 3000); // 增加到 3 秒,给分段发送和服务器响应更多时间
136
+ });
137
+ }
138
+ /**
139
+ * 测试场景2:粘包测试 - 将多个完整包合并发送
140
+ */
141
+ async testStickyPacket(port) {
142
+ return new Promise((resolve) => {
143
+ const client = new net.Socket();
144
+ let receivedPackets = 0;
145
+ const expectedPackets = 3;
146
+ // 创建3个测试包
147
+ const packets = [];
148
+ for (let i = 1; i <= expectedPackets; i++) {
149
+ packets.push(this.createTestPacket(i));
150
+ }
151
+ // 合并所有包
152
+ const combinedPacket = Buffer.concat(packets);
153
+ console.log(`📦 [粘包测试] 连接成功,发送 ${expectedPackets} 个合并的数据包...`);
154
+ console.log(` 合并包总大小: ${combinedPacket.length} 字节`);
155
+ console.log(` 单个包大小: ${packets.map((p) => p.length).join(', ')} 字节`);
156
+ client.connect(port, '127.0.0.1', () => {
157
+ // 一次性发送所有包
158
+ client.write(combinedPacket);
159
+ console.log(` ✅ 已发送合并包`);
160
+ });
161
+ const receiveBuffer = [];
162
+ client.on('data', (data) => {
163
+ receiveBuffer.push(data);
164
+ const fullBuffer = Buffer.concat(receiveBuffer);
165
+ // 提取所有完整包
166
+ const { packets: extractedPackets, remaining } = this.protocolHandler.extractAllCompletePackets(fullBuffer);
167
+ if (extractedPackets.length > 0) {
168
+ receivedPackets += extractedPackets.length;
169
+ console.log(` ✅ 接收到 ${extractedPackets.length} 个完整包 (累计: ${receivedPackets})`);
170
+ // 验证每个包
171
+ for (const packet of extractedPackets) {
172
+ try {
173
+ const parseResult = this.protocolHandler.parse(packet);
174
+ console.log(` - 包 ${parseResult.requestId}: ${JSON.stringify(parseResult.data)}`);
175
+ }
176
+ catch (error) {
177
+ console.error(` - ❌ 解析失败:`, error);
178
+ }
179
+ }
180
+ }
181
+ // 更新接收缓冲区
182
+ receiveBuffer.length = 0;
183
+ if (remaining) {
184
+ receiveBuffer.push(remaining);
185
+ }
186
+ });
187
+ client.on('error', (error) => {
188
+ console.error(` ❌ 连接错误:`, error.message);
189
+ resolve({
190
+ name: '粘包测试',
191
+ passed: false,
192
+ error: error.message,
193
+ receivedPackets: 0,
194
+ expectedPackets,
195
+ });
196
+ });
197
+ // 等待接收完成
198
+ setTimeout(() => {
199
+ client.destroy();
200
+ const passed = receivedPackets === expectedPackets;
201
+ console.log(` ${passed ? '✅' : '❌'} 测试结果: 期望 ${expectedPackets} 个包,实际收到 ${receivedPackets} 个包\n`);
202
+ resolve({
203
+ name: '粘包测试',
204
+ passed,
205
+ receivedPackets,
206
+ expectedPackets,
207
+ });
208
+ }, 2000);
209
+ });
210
+ }
211
+ /**
212
+ * 测试场景3:混合场景 - 半包 + 粘包
213
+ */
214
+ async testMixedPacket(port) {
215
+ return new Promise((resolve) => {
216
+ const client = new net.Socket();
217
+ let receivedPackets = 0;
218
+ const expectedPackets = 3;
219
+ // 创建3个测试包
220
+ const packets = [];
221
+ for (let i = 1; i <= expectedPackets; i++) {
222
+ packets.push(this.createTestPacket(i));
223
+ }
224
+ // 第一个包:分成两段发送(半包)
225
+ // 第二、三个包:合并发送(粘包)
226
+ const firstPacket = packets[0];
227
+ const firstHalf = firstPacket.slice(0, Math.floor(firstPacket.length / 2));
228
+ const secondHalf = firstPacket.slice(Math.floor(firstPacket.length / 2));
229
+ const remainingPackets = Buffer.concat(packets.slice(1));
230
+ console.log(`📦 [混合场景测试] 连接成功,发送混合数据包...`);
231
+ console.log(` 第1个包: 分成两段发送 (${firstHalf.length} + ${secondHalf.length} 字节)`);
232
+ console.log(` 第2-3个包: 合并发送 (${remainingPackets.length} 字节)`);
233
+ client.connect(port, '127.0.0.1', () => {
234
+ // 先发送第一个包的前半段
235
+ client.write(firstHalf);
236
+ console.log(` ✅ 发送第1个包的前半段: ${firstHalf.length} 字节`);
237
+ // 延迟后发送第一个包的后半段 + 其他包
238
+ setTimeout(() => {
239
+ const combined = Buffer.concat([secondHalf, remainingPackets]);
240
+ client.write(combined);
241
+ console.log(` ✅ 发送第1个包的后半段 + 第2-3个包: ${combined.length} 字节`);
242
+ }, 50);
243
+ });
244
+ const receiveBuffer = [];
245
+ client.on('data', (data) => {
246
+ receiveBuffer.push(data);
247
+ const fullBuffer = Buffer.concat(receiveBuffer);
248
+ // 提取所有完整包
249
+ const { packets: extractedPackets, remaining } = this.protocolHandler.extractAllCompletePackets(fullBuffer);
250
+ if (extractedPackets.length > 0) {
251
+ receivedPackets += extractedPackets.length;
252
+ console.log(` ✅ 接收到 ${extractedPackets.length} 个完整包 (累计: ${receivedPackets})`);
253
+ // 验证每个包
254
+ for (const packet of extractedPackets) {
255
+ try {
256
+ const parseResult = this.protocolHandler.parse(packet);
257
+ console.log(` - 包 ${parseResult.requestId}: ${JSON.stringify(parseResult.data)}`);
258
+ }
259
+ catch (error) {
260
+ console.error(` - ❌ 解析失败:`, error);
261
+ }
262
+ }
263
+ }
264
+ // 更新接收缓冲区
265
+ receiveBuffer.length = 0;
266
+ if (remaining) {
267
+ receiveBuffer.push(remaining);
268
+ }
269
+ });
270
+ client.on('error', (error) => {
271
+ console.error(` ❌ 连接错误:`, error.message);
272
+ resolve({
273
+ name: '混合场景测试',
274
+ passed: false,
275
+ error: error.message,
276
+ receivedPackets: 0,
277
+ expectedPackets,
278
+ });
279
+ });
280
+ // 等待接收完成
281
+ setTimeout(() => {
282
+ client.destroy();
283
+ const passed = receivedPackets === expectedPackets;
284
+ console.log(` ${passed ? '✅' : '❌'} 测试结果: 期望 ${expectedPackets} 个包,实际收到 ${receivedPackets} 个包\n`);
285
+ resolve({
286
+ name: '混合场景测试',
287
+ passed,
288
+ receivedPackets,
289
+ expectedPackets,
290
+ });
291
+ }, 3000);
292
+ });
293
+ }
294
+ /**
295
+ * 测试场景4:大量粘包测试
296
+ */
297
+ async testManyStickyPackets(port) {
298
+ return new Promise((resolve) => {
299
+ const client = new net.Socket();
300
+ let receivedPackets = 0;
301
+ const expectedPackets = 10;
302
+ // 创建10个测试包
303
+ const packets = [];
304
+ for (let i = 1; i <= expectedPackets; i++) {
305
+ packets.push(this.createTestPacket(i));
306
+ }
307
+ // 合并所有包
308
+ const combinedPacket = Buffer.concat(packets);
309
+ console.log(`📦 [大量粘包测试] 连接成功,发送 ${expectedPackets} 个合并的数据包...`);
310
+ console.log(` 合并包总大小: ${combinedPacket.length} 字节`);
311
+ client.connect(port, '127.0.0.1', () => {
312
+ client.write(combinedPacket);
313
+ console.log(` ✅ 已发送合并包`);
314
+ });
315
+ const receiveBuffer = [];
316
+ client.on('data', (data) => {
317
+ receiveBuffer.push(data);
318
+ const fullBuffer = Buffer.concat(receiveBuffer);
319
+ // 提取所有完整包
320
+ const { packets: extractedPackets, remaining } = this.protocolHandler.extractAllCompletePackets(fullBuffer);
321
+ if (extractedPackets.length > 0) {
322
+ receivedPackets += extractedPackets.length;
323
+ console.log(` ✅ 接收到 ${extractedPackets.length} 个完整包 (累计: ${receivedPackets}/${expectedPackets})`);
324
+ }
325
+ // 更新接收缓冲区
326
+ receiveBuffer.length = 0;
327
+ if (remaining) {
328
+ receiveBuffer.push(remaining);
329
+ }
330
+ });
331
+ client.on('error', (error) => {
332
+ console.error(` ❌ 连接错误:`, error.message);
333
+ resolve({
334
+ name: '大量粘包测试',
335
+ passed: false,
336
+ error: error.message,
337
+ receivedPackets: 0,
338
+ expectedPackets,
339
+ });
340
+ });
341
+ // 等待接收完成
342
+ setTimeout(() => {
343
+ client.destroy();
344
+ const passed = receivedPackets === expectedPackets;
345
+ console.log(` ${passed ? '✅' : '❌'} 测试结果: 期望 ${expectedPackets} 个包,实际收到 ${receivedPackets} 个包\n`);
346
+ resolve({
347
+ name: '大量粘包测试',
348
+ passed,
349
+ receivedPackets,
350
+ expectedPackets,
351
+ });
352
+ }, 3000);
353
+ });
354
+ }
355
+ /**
356
+ * 运行所有测试
357
+ */
358
+ async runAllTests(port = 8080) {
359
+ console.log('🚀 开始半包和粘包测试\n');
360
+ console.log('='.repeat(60));
361
+ console.log('');
362
+ // 测试1:半包
363
+ const result1 = await this.testHalfPacket(port);
364
+ this.testResults.push(result1);
365
+ await new Promise((resolve) => setTimeout(resolve, 500));
366
+ // 测试2:粘包
367
+ const result2 = await this.testStickyPacket(port);
368
+ this.testResults.push(result2);
369
+ await new Promise((resolve) => setTimeout(resolve, 500));
370
+ // 测试3:混合场景
371
+ const result3 = await this.testMixedPacket(port);
372
+ this.testResults.push(result3);
373
+ await new Promise((resolve) => setTimeout(resolve, 500));
374
+ // 测试4:大量粘包
375
+ const result4 = await this.testManyStickyPackets(port);
376
+ this.testResults.push(result4);
377
+ // 打印测试总结
378
+ console.log('='.repeat(60));
379
+ console.log('📊 测试总结\n');
380
+ let passedCount = 0;
381
+ for (const result of this.testResults) {
382
+ const status = result.passed ? '✅ 通过' : '❌ 失败';
383
+ console.log(`${status} - ${result.name}`);
384
+ console.log(` 期望: ${result.expectedPackets} 个包, 实际: ${result.receivedPackets} 个包`);
385
+ if (result.error) {
386
+ console.log(` 错误: ${result.error}`);
387
+ }
388
+ console.log('');
389
+ if (result.passed)
390
+ passedCount++;
391
+ }
392
+ console.log('='.repeat(60));
393
+ console.log(`总计: ${passedCount}/${this.testResults.length} 个测试通过\n`);
394
+ if (passedCount === this.testResults.length) {
395
+ console.log('🎉 所有测试通过!');
396
+ }
397
+ else {
398
+ console.log('⚠️ 部分测试失败,请检查协议处理逻辑');
399
+ }
400
+ }
401
+ }
402
+ // 主函数
403
+ async function main() {
404
+ const port = parseInt(process.env.PORT || '8080', 10);
405
+ const tester = new PacketSplitTester();
406
+ await tester.runAllTests(port);
407
+ }
408
+ // 如果直接运行此文件,执行测试
409
+ if (import.meta.url === `file://${process.argv[1]?.replace(/\\/g, '/')}` ||
410
+ process.argv[1]?.includes('test-packet-split.ts')) {
411
+ main().catch((error) => {
412
+ console.error('测试执行错误:', error);
413
+ process.exit(1);
414
+ });
415
+ }
416
+ export { PacketSplitTester };
417
+ //# sourceMappingURL=test-packet-split.js.map