@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,168 @@
1
+ import * as net from 'net';
2
+ import type { SocketConnectOptions, HeartbeatResponseChecker } from './types.js';
3
+ /**
4
+ * tcp连接管理器
5
+ * 负责处理 TCP 连接、重连、超时检测等
6
+ */
7
+ export declare class TcpWrapper {
8
+ /** TCP Socket 实例 */
9
+ private socket;
10
+ /** 连接超时定时器 */
11
+ private connectTimeout;
12
+ /** 重连定时器 */
13
+ private retryConnectTimeout;
14
+ /** 心跳发送定时器 */
15
+ private heartbeatInterval;
16
+ /** 心跳响应超时定时器 */
17
+ private heartbeatTimeout;
18
+ /** 连接地址 */
19
+ private address;
20
+ /** 连接端口 */
21
+ private port;
22
+ /** 连接配置选项 */
23
+ private connectOptions;
24
+ /** 运行时的连接状态 */
25
+ private connectionActive;
26
+ /** 是否启用自动重连 */
27
+ private autoReconnect;
28
+ /** 心跳间隔(毫秒) */
29
+ private heartbeatIntervalMs;
30
+ /** 心跳超时时间(毫秒) */
31
+ private heartbeatTimeoutMs;
32
+ /** 是否有待响应的心跳 */
33
+ private pendingHeartbeat;
34
+ /** 连续心跳超时次数 */
35
+ private heartbeatTimeoutCount;
36
+ /** 心跳响应识别函数 */
37
+ private heartbeatResponseChecker;
38
+ /** 最大重连次数,0 表示无限制 */
39
+ private maxReconnectAttempts;
40
+ /** 是否启用指数退避 */
41
+ private enableExponentialBackoff;
42
+ /** 指数退避的最大间隔(毫秒) */
43
+ private maxReconnectInterval;
44
+ /** 当前重连次数 */
45
+ private reconnectAttempts;
46
+ /** 基础重连间隔(毫秒) */
47
+ private reconnectInterval;
48
+ /** 连接开始时间(用于计算握手时间) */
49
+ private connectStartTime;
50
+ /** 握手超时尝试次数 */
51
+ private handshakeTimeoutAttempts;
52
+ /** 最大握手超时尝试次数 */
53
+ private readonly maxHandshakeTimeoutAttempts;
54
+ /** 基础握手重试间隔(毫秒) */
55
+ private readonly baseHandshakeRetryInterval;
56
+ /** 最大握手重试间隔(毫秒) */
57
+ private readonly maxHandshakeRetryInterval;
58
+ /** 连接成功回调 */
59
+ private onConnected?;
60
+ /** 连接断开回调(自动重连时会触发) */
61
+ private onDisconnected?;
62
+ /** 接收数据回调 */
63
+ private onData?;
64
+ /** 错误回调 */
65
+ private onError?;
66
+ /** 连接关闭回调(手动断开或重连失败时触发) */
67
+ private onClose?;
68
+ constructor();
69
+ /**
70
+ * 设置 Socket 事件监听
71
+ */
72
+ private setupSocketEvents;
73
+ /**
74
+ * 检查是否达到最大重连次数
75
+ */
76
+ private hasReachedMaxAttempts;
77
+ /**
78
+ * 计算重连间隔(考虑指数退避)
79
+ */
80
+ private calculateReconnectInterval;
81
+ /**
82
+ * 计算握手超时重试间隔(使用指数退避)
83
+ */
84
+ private calculateHandshakeRetryInterval;
85
+ /**
86
+ * 触发重连
87
+ */
88
+ private triggerRetryConnection;
89
+ /**
90
+ * 执行重连
91
+ */
92
+ private retryConnection;
93
+ /**
94
+ * 启动心跳
95
+ */
96
+ private startHeartbeat;
97
+ /**
98
+ * 停止心跳
99
+ */
100
+ private stopHeartbeat;
101
+ /**
102
+ * 发送心跳包
103
+ */
104
+ private sendHeartbeat;
105
+ /**
106
+ * 清除心跳响应超时定时器
107
+ */
108
+ private clearHeartbeatTimeout;
109
+ /**
110
+ * 设置连接超时
111
+ */
112
+ private setConnectTimeout;
113
+ /**
114
+ * 清除连接超时定时器
115
+ */
116
+ private clearConnectTimeout;
117
+ /**
118
+ * 清除重连定时器
119
+ */
120
+ private clearRetryConnectTimeout;
121
+ /**
122
+ * 清理资源
123
+ */
124
+ private cleanup;
125
+ /**
126
+ * 设置事件回调
127
+ */
128
+ setEventHandlers(handlers: {
129
+ onConnected?: () => void;
130
+ onDisconnected?: () => void;
131
+ onData?: (data: Buffer) => void;
132
+ onError?: (error: Error) => void;
133
+ onClose?: () => void;
134
+ }): void;
135
+ /**
136
+ * 连接
137
+ */
138
+ connect(host: string, port: number, options: SocketConnectOptions): void;
139
+ /**
140
+ * 断开连接
141
+ */
142
+ disconnect(): void;
143
+ /**
144
+ * 获取 Socket 实例
145
+ */
146
+ getSocket(): net.Socket | null;
147
+ /**
148
+ * 检查是否已连接
149
+ */
150
+ isConnected(): boolean;
151
+ /**
152
+ * 设置心跳响应识别函数
153
+ */
154
+ setHeartbeatResponseChecker(checker: HeartbeatResponseChecker): void;
155
+ /**
156
+ * 获取当前连接地址
157
+ */
158
+ getAddress(): string | null;
159
+ /**
160
+ * 获取当前连接端口
161
+ */
162
+ getPort(): number | null;
163
+ /**
164
+ * 获取当前重连次数
165
+ */
166
+ getReconnectAttempts(): number;
167
+ }
168
+ //# sourceMappingURL=tcpWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tcpWrapper.d.ts","sourceRoot":"","sources":["../../../src/packages/tcp/tcpWrapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,472 @@
1
+ // ALL_CODE_LINE: 450
2
+ // AI_CODE_LINE: 40
3
+ import * as net from 'net';
4
+ import { DEFAULT_AUTO_RECONNECT, DEFAULT_RECONNECT_INTERVAL, DEFAULT_HEARTBEAT_INTERVAL, DEFAULT_HEARTBEAT_TIMEOUT, DEFAULT_MAX_RECONNECT_INTERVAL, DEFAULT_ENABLE_EXPONENTIAL_BACKOFF, DEFAULT_MAX_RECONNECT_ATTEMPTS, } from './constants.js';
5
+ /**
6
+ * tcp连接管理器
7
+ * 负责处理 TCP 连接、重连、超时检测等
8
+ */
9
+ export class TcpWrapper {
10
+ /** TCP Socket 实例 */
11
+ socket = null;
12
+ /** 连接超时定时器 */
13
+ connectTimeout = null;
14
+ /** 重连定时器 */
15
+ retryConnectTimeout = null;
16
+ /** 心跳发送定时器 */
17
+ heartbeatInterval = null;
18
+ /** 心跳响应超时定时器 */
19
+ heartbeatTimeout = null;
20
+ /** 连接地址 */
21
+ address = null;
22
+ /** 连接端口 */
23
+ port = null;
24
+ /** 连接配置选项 */
25
+ connectOptions = null;
26
+ /** 运行时的连接状态 */
27
+ connectionActive = false;
28
+ /** 是否启用自动重连 */
29
+ autoReconnect = false;
30
+ /** 心跳间隔(毫秒) */
31
+ heartbeatIntervalMs = 5000;
32
+ /** 心跳超时时间(毫秒) */
33
+ heartbeatTimeoutMs = 5000;
34
+ /** 是否有待响应的心跳 */
35
+ pendingHeartbeat = false;
36
+ /** 连续心跳超时次数 */
37
+ heartbeatTimeoutCount = 0;
38
+ /** 心跳响应识别函数 */
39
+ heartbeatResponseChecker = (data) => {
40
+ // data 是 Buffer 对象,需要转换为字符串比较
41
+ // 心跳响应可能是 "pong"(4字节)或 "pong\n"(5字节,带换行符)
42
+ if (data.length === 4) {
43
+ // 精确匹配 4 字节的 "pong"
44
+ return data.toString('utf8') === 'pong';
45
+ }
46
+ else if (data.length === 5) {
47
+ // 匹配 5 字节的 "pong\n" 或 "pong\r"
48
+ const dataStr = data.toString('utf8');
49
+ return dataStr === 'pong\n' || dataStr === 'pong\r';
50
+ }
51
+ else if (data.length > 4) {
52
+ // 检查数据开头是否是 "pong"(处理粘包情况:pong + 其他数据)
53
+ const first4Bytes = data.slice(0, 4);
54
+ if (first4Bytes.toString('utf8') === 'pong') {
55
+ // 检查第5个字节是否是换行符或数据结束
56
+ if (data.length === 5 || data[4] === 0x0a || data[4] === 0x0d) {
57
+ return true;
58
+ }
59
+ }
60
+ }
61
+ return false;
62
+ };
63
+ /** 最大重连次数,0 表示无限制 */
64
+ maxReconnectAttempts = 0;
65
+ /** 是否启用指数退避 */
66
+ enableExponentialBackoff = true;
67
+ /** 指数退避的最大间隔(毫秒) */
68
+ maxReconnectInterval = 60000;
69
+ /** 当前重连次数 */
70
+ reconnectAttempts = 0;
71
+ /** 基础重连间隔(毫秒) */
72
+ reconnectInterval = 5000;
73
+ /** 连接开始时间(用于计算握手时间) */
74
+ connectStartTime = 0;
75
+ /** 握手超时尝试次数 */
76
+ handshakeTimeoutAttempts = 0;
77
+ /** 最大握手超时尝试次数 */
78
+ maxHandshakeTimeoutAttempts = 3;
79
+ /** 基础握手重试间隔(毫秒) */
80
+ baseHandshakeRetryInterval = 1000;
81
+ /** 最大握手重试间隔(毫秒) */
82
+ maxHandshakeRetryInterval = 3000;
83
+ /** 连接成功回调 */
84
+ onConnected;
85
+ /** 连接断开回调(自动重连时会触发) */
86
+ onDisconnected;
87
+ /** 接收数据回调 */
88
+ onData;
89
+ /** 错误回调 */
90
+ onError;
91
+ /** 连接关闭回调(手动断开或重连失败时触发) */
92
+ onClose;
93
+ constructor() { }
94
+ /**
95
+ * 设置 Socket 事件监听
96
+ */
97
+ setupSocketEvents() {
98
+ if (!this.socket)
99
+ return;
100
+ this.socket.on('connect', () => {
101
+ this.clearConnectTimeout();
102
+ // 计算TCP握手时间
103
+ if (this.connectStartTime > 0) {
104
+ this.connectStartTime = 0; // 重置时间戳
105
+ }
106
+ // 连接成功,重置所有计数器
107
+ this.reconnectAttempts = 0;
108
+ this.heartbeatTimeoutCount = 0;
109
+ this.handshakeTimeoutAttempts = 0; // 重置握手超时计数
110
+ this.startHeartbeat();
111
+ // 触发连接成功回调
112
+ this.onConnected?.();
113
+ });
114
+ this.socket.on('data', (data) => {
115
+ // 检查是否是心跳响应
116
+ if (this.heartbeatResponseChecker?.(data)) {
117
+ this.clearHeartbeatTimeout();
118
+ this.pendingHeartbeat = false;
119
+ this.heartbeatTimeoutCount = 0; // 重置超时计数
120
+ return;
121
+ }
122
+ this.onData?.(data);
123
+ });
124
+ this.socket.on('close', (_hadError) => {
125
+ this.clearConnectTimeout();
126
+ this.stopHeartbeat();
127
+ this.cleanup();
128
+ if (this.connectionActive && this.autoReconnect) {
129
+ this.onDisconnected?.();
130
+ this.triggerRetryConnection();
131
+ }
132
+ else {
133
+ this.connectionActive = false;
134
+ this.onClose?.();
135
+ }
136
+ });
137
+ this.socket.on('error', (error) => {
138
+ this.clearConnectTimeout();
139
+ this.onError?.(error);
140
+ if (this.connectionActive && this.autoReconnect && this.socket?.destroyed) {
141
+ this.triggerRetryConnection();
142
+ }
143
+ });
144
+ this.socket.on('timeout', () => {
145
+ this.clearConnectTimeout();
146
+ this.socket?.destroy();
147
+ this.onError?.(new Error('Connection timeout'));
148
+ });
149
+ }
150
+ /**
151
+ * 检查是否达到最大重连次数
152
+ */
153
+ hasReachedMaxAttempts() {
154
+ return this.maxReconnectAttempts > 0 && this.reconnectAttempts >= this.maxReconnectAttempts;
155
+ }
156
+ /**
157
+ * 计算重连间隔(考虑指数退避)
158
+ */
159
+ calculateReconnectInterval() {
160
+ // 指数退避:interval = baseInterval * 2^attempts,但不超过 maxReconnectInterval
161
+ return !this.enableExponentialBackoff
162
+ ? this.reconnectInterval
163
+ : Math.min(this.reconnectInterval * Math.pow(2, this.reconnectAttempts), this.maxReconnectInterval);
164
+ }
165
+ /**
166
+ * 计算握手超时重试间隔(使用指数退避)
167
+ */
168
+ calculateHandshakeRetryInterval() {
169
+ // 指数退避:interval = baseInterval * 2^attempts,但不超过 maxHandshakeRetryInterval
170
+ // attempts 从 0 开始,所以第一次重试是 baseInterval * 2^0 = baseInterval
171
+ return Math.min(this.baseHandshakeRetryInterval * Math.pow(2, this.handshakeTimeoutAttempts - 1), this.maxHandshakeRetryInterval);
172
+ }
173
+ /**
174
+ * 触发重连
175
+ */
176
+ triggerRetryConnection() {
177
+ if (!this.connectionActive || !this.autoReconnect)
178
+ return;
179
+ // 检查最大重连次数
180
+ if (this.hasReachedMaxAttempts()) {
181
+ this.connectionActive = false;
182
+ this.onClose?.();
183
+ return;
184
+ }
185
+ // 如果已有重连定时器,不重复设置
186
+ if (this.retryConnectTimeout)
187
+ return;
188
+ const interval = this.calculateReconnectInterval();
189
+ this.retryConnectTimeout = setTimeout(() => {
190
+ this.retryConnection();
191
+ }, interval);
192
+ }
193
+ /**
194
+ * 执行重连
195
+ */
196
+ retryConnection() {
197
+ this.clearRetryConnectTimeout();
198
+ if (!this.connectionActive)
199
+ return;
200
+ if (this.isConnected())
201
+ return;
202
+ // 再次检查最大重连次数(防止在等待期间达到上限)||如果连接信息缺失,停止重连,避免无限递归
203
+ if (this.hasReachedMaxAttempts() || !this.connectOptions || !this.address || !this.port) {
204
+ this.connectionActive = false;
205
+ this.onClose?.();
206
+ return;
207
+ }
208
+ // 增加重连计数
209
+ this.reconnectAttempts++;
210
+ try {
211
+ this.connect(this.address, this.port, this.connectOptions);
212
+ }
213
+ catch (error) {
214
+ this.onError?.(error);
215
+ }
216
+ }
217
+ /**
218
+ * 启动心跳
219
+ */
220
+ startHeartbeat() {
221
+ if (this.heartbeatInterval)
222
+ return;
223
+ // 立即发送一次心跳
224
+ this.sendHeartbeat();
225
+ // 设置定时发送心跳
226
+ this.heartbeatInterval = setInterval(() => {
227
+ this.sendHeartbeat();
228
+ }, this.heartbeatIntervalMs);
229
+ }
230
+ /**
231
+ * 停止心跳
232
+ */
233
+ stopHeartbeat() {
234
+ if (this.heartbeatInterval) {
235
+ clearInterval(this.heartbeatInterval);
236
+ this.heartbeatInterval = null;
237
+ }
238
+ this.clearHeartbeatTimeout();
239
+ this.pendingHeartbeat = false;
240
+ this.heartbeatTimeoutCount = 0; // 重置超时计数
241
+ }
242
+ /**
243
+ * 发送心跳包
244
+ */
245
+ sendHeartbeat() {
246
+ if (!this.socket?.writable || this.socket.destroyed)
247
+ return;
248
+ try {
249
+ this.socket.write('ping');
250
+ this.pendingHeartbeat = true;
251
+ // 设置心跳响应超时
252
+ this.clearHeartbeatTimeout();
253
+ this.heartbeatTimeout = setTimeout(() => {
254
+ if (this.pendingHeartbeat) {
255
+ this.heartbeatTimeoutCount++;
256
+ // 只有连续2次心跳超时才清理socket
257
+ if (this.heartbeatTimeoutCount >= 2) {
258
+ this.connectionActive = false;
259
+ this.onDisconnected?.();
260
+ this.socket?.destroy();
261
+ // 如果启用了自动重连,触发重连
262
+ if (this.autoReconnect) {
263
+ this.connectionActive = true;
264
+ this.triggerRetryConnection();
265
+ }
266
+ }
267
+ }
268
+ }, this.heartbeatTimeoutMs);
269
+ }
270
+ catch (error) {
271
+ this.onError?.(error);
272
+ }
273
+ }
274
+ /**
275
+ * 清除心跳响应超时定时器
276
+ */
277
+ clearHeartbeatTimeout() {
278
+ if (this.heartbeatTimeout) {
279
+ clearTimeout(this.heartbeatTimeout);
280
+ this.heartbeatTimeout = null;
281
+ }
282
+ }
283
+ /**
284
+ * 设置连接超时
285
+ */
286
+ setConnectTimeout() {
287
+ this.clearConnectTimeout();
288
+ this.connectTimeout = setTimeout(() => {
289
+ if (this.socket && !this.socket.destroyed) {
290
+ this.handshakeTimeoutAttempts++;
291
+ // 如果未达到最大尝试次数,重试连接
292
+ if (this.handshakeTimeoutAttempts < this.maxHandshakeTimeoutAttempts) {
293
+ // 清理当前socket
294
+ this.socket.destroy();
295
+ this.socket = null;
296
+ // 计算重试延迟(使用指数退避)
297
+ const retryDelay = this.calculateHandshakeRetryInterval();
298
+ // 重新尝试连接
299
+ if (this.address && this.port && this.connectOptions) {
300
+ setTimeout(() => {
301
+ if (this.connectionActive && !this.isConnected()) {
302
+ try {
303
+ // 重新创建连接
304
+ this.socket = net.createConnection({
305
+ host: this.address,
306
+ port: this.port,
307
+ keepAlive: true,
308
+ keepAliveInitialDelay: 1000,
309
+ });
310
+ // 重新设置超时和事件
311
+ this.setConnectTimeout();
312
+ this.setupSocketEvents();
313
+ }
314
+ catch (error) {
315
+ this.onError?.(error);
316
+ }
317
+ }
318
+ }, retryDelay);
319
+ }
320
+ }
321
+ else {
322
+ // 超过最大尝试次数,断开连接
323
+ this.connectionActive = false;
324
+ this.socket.destroy();
325
+ this.onError?.(new Error(`Connection timeout after ${this.maxHandshakeTimeoutAttempts} attempts`));
326
+ this.onClose?.();
327
+ }
328
+ }
329
+ }, 1000);
330
+ }
331
+ /**
332
+ * 清除连接超时定时器
333
+ */
334
+ clearConnectTimeout() {
335
+ if (this.connectTimeout) {
336
+ clearTimeout(this.connectTimeout);
337
+ this.connectTimeout = null;
338
+ }
339
+ }
340
+ /**
341
+ * 清除重连定时器
342
+ */
343
+ clearRetryConnectTimeout() {
344
+ if (this.retryConnectTimeout) {
345
+ clearTimeout(this.retryConnectTimeout);
346
+ this.retryConnectTimeout = null;
347
+ }
348
+ }
349
+ /**
350
+ * 清理资源
351
+ */
352
+ cleanup() {
353
+ this.clearConnectTimeout();
354
+ }
355
+ /**
356
+ * 设置事件回调
357
+ */
358
+ setEventHandlers(handlers) {
359
+ this.onConnected = handlers.onConnected;
360
+ this.onDisconnected = handlers.onDisconnected;
361
+ this.onData = handlers.onData;
362
+ this.onError = handlers.onError;
363
+ this.onClose = handlers.onClose;
364
+ }
365
+ /**
366
+ * 连接
367
+ */
368
+ connect(host, port, options) {
369
+ if (!host || !port) {
370
+ this.onError?.(new Error(`Invalid connection parameters: host=${host}, port=${port}`));
371
+ return;
372
+ }
373
+ // 保存连接信息用于重连
374
+ this.address = host;
375
+ this.port = port;
376
+ this.connectOptions = { ...options };
377
+ this.connectionActive = true;
378
+ // 配置重连和心跳
379
+ this.autoReconnect = options.autoReconnect ?? DEFAULT_AUTO_RECONNECT;
380
+ this.reconnectInterval = options.reconnectInterval ?? DEFAULT_RECONNECT_INTERVAL;
381
+ this.heartbeatIntervalMs = options.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;
382
+ this.heartbeatTimeoutMs = options.heartbeatTimeout ?? DEFAULT_HEARTBEAT_TIMEOUT;
383
+ this.maxReconnectAttempts = options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;
384
+ this.enableExponentialBackoff = options.enableExponentialBackoff ?? DEFAULT_ENABLE_EXPONENTIAL_BACKOFF;
385
+ this.maxReconnectInterval = options.maxReconnectInterval ?? DEFAULT_MAX_RECONNECT_INTERVAL;
386
+ // 重置重连计数器和握手超时计数器(新连接时)
387
+ this.reconnectAttempts = 0;
388
+ this.handshakeTimeoutAttempts = 0;
389
+ // 如果已有 socket,先清理
390
+ if (this.socket) {
391
+ this.socket.removeAllListeners();
392
+ if (!this.socket.destroyed) {
393
+ this.socket.destroy();
394
+ }
395
+ this.socket = null;
396
+ }
397
+ // 记录连接开始时间(用于计算握手时间)
398
+ this.connectStartTime = Date.now();
399
+ // 创建 TCP 连接
400
+ this.socket = net.createConnection({
401
+ host,
402
+ port,
403
+ keepAlive: true,
404
+ keepAliveInitialDelay: 1000, // TCP keepalive 初始延迟时间(毫秒)
405
+ });
406
+ // 设置连接超时( 1000ms)
407
+ this.setConnectTimeout();
408
+ // 绑定事件
409
+ this.setupSocketEvents();
410
+ }
411
+ /**
412
+ * 断开连接
413
+ */
414
+ disconnect() {
415
+ this.connectionActive = false;
416
+ this.clearConnectTimeout();
417
+ this.clearRetryConnectTimeout();
418
+ this.stopHeartbeat();
419
+ if (this.socket) {
420
+ if (this.socket.writable) {
421
+ this.socket.end();
422
+ }
423
+ else {
424
+ this.socket.destroy();
425
+ }
426
+ this.socket = null;
427
+ }
428
+ // 重置连接信息和所有计数器
429
+ this.address = null;
430
+ this.port = null;
431
+ this.connectOptions = null;
432
+ this.reconnectAttempts = 0;
433
+ this.handshakeTimeoutAttempts = 0;
434
+ }
435
+ /**
436
+ * 获取 Socket 实例
437
+ */
438
+ getSocket() {
439
+ return this.socket;
440
+ }
441
+ /**
442
+ * 检查是否已连接
443
+ */
444
+ isConnected() {
445
+ return this.socket !== null && !this.socket.destroyed && this.socket.writable;
446
+ }
447
+ /**
448
+ * 设置心跳响应识别函数
449
+ */
450
+ setHeartbeatResponseChecker(checker) {
451
+ this.heartbeatResponseChecker = checker || ((data) => data.toString() === 'pong');
452
+ }
453
+ /**
454
+ * 获取当前连接地址
455
+ */
456
+ getAddress() {
457
+ return this.address;
458
+ }
459
+ /**
460
+ * 获取当前连接端口
461
+ */
462
+ getPort() {
463
+ return this.port;
464
+ }
465
+ /**
466
+ * 获取当前重连次数
467
+ */
468
+ getReconnectAttempts() {
469
+ return this.reconnectAttempts;
470
+ }
471
+ }
472
+ //# sourceMappingURL=tcpWrapper.js.map