0
# Connection Management
1
2
Active WebSocket connection handling for bidirectional communication between client and server with comprehensive message processing, event handling, and connection lifecycle management.
3
4
## Capabilities
5
6
### WebSocketConnection
7
8
Represents an active WebSocket connection for both client and server sides.
9
10
```javascript { .api }
11
/**
12
* Active WebSocket connection for bidirectional communication
13
* @param socket - TCP socket
14
* @param extensions - Negotiated extensions array
15
* @param protocol - Negotiated protocol string
16
* @param maskOutgoingPackets - Whether to mask outgoing packets
17
* @param config - Connection configuration
18
*/
19
class WebSocketConnection extends EventEmitter {
20
/**
21
* Send text or binary data (auto-detects type)
22
* @param data - String or Buffer to send
23
* @param callback - Optional callback for completion/error
24
*/
25
send(data: string | Buffer, callback?: (error?: Error) => void): void;
26
27
/**
28
* Send UTF-8 text data
29
* @param data - UTF-8 string to send
30
* @param callback - Optional callback for completion/error
31
*/
32
sendUTF(data: string, callback?: (error?: Error) => void): void;
33
34
/**
35
* Send binary data
36
* @param data - Buffer containing binary data
37
* @param callback - Optional callback for completion/error
38
*/
39
sendBytes(data: Buffer, callback?: (error?: Error) => void): void;
40
41
/**
42
* Send ping frame with optional payload
43
* @param data - Optional Buffer payload for ping frame
44
*/
45
ping(data?: Buffer): void;
46
47
/**
48
* Send pong frame (usually sent automatically in response to ping)
49
* @param binaryPayload - Buffer payload for pong frame
50
*/
51
pong(binaryPayload: Buffer): void;
52
53
/**
54
* Initiate clean connection close
55
* @param reasonCode - Close reason code (default: 1000)
56
* @param description - Human-readable close reason
57
*/
58
close(reasonCode?: number, description?: string): void;
59
60
/**
61
* Force close connection immediately
62
* @param reasonCode - Close reason code
63
* @param description - Human-readable close reason
64
* @param skipCloseFrame - Skip sending close frame
65
*/
66
drop(reasonCode?: number, description?: string, skipCloseFrame?: boolean): void;
67
68
/** Pause reading from socket */
69
pause(): void;
70
71
/** Resume reading from socket */
72
resume(): void;
73
74
/** Boolean connection status */
75
readonly connected: boolean;
76
77
/** Connection state: 'open', 'peer_requested_close', 'ending', 'closed' */
78
readonly state: string;
79
80
/** Negotiated WebSocket protocol */
81
readonly protocol: string;
82
83
/** Negotiated extensions (currently always empty array) */
84
readonly extensions: any[];
85
86
/** Remote IP address */
87
readonly remoteAddress: string;
88
89
/** Array of addresses including X-Forwarded-For */
90
readonly remoteAddresses: string[];
91
92
/** Close reason code (set after close) */
93
readonly closeReasonCode: number;
94
95
/** Close reason description (set after close) */
96
readonly closeDescription: string;
97
98
/** WebSocket protocol version (8 or 13) */
99
readonly webSocketVersion: number;
100
101
/** Underlying TCP socket */
102
readonly socket: object;
103
}
104
```
105
106
**Events:**
107
108
- `'message'` - `(WebSocketMessage)` - Message received
109
- `'frame'` - `(WebSocketFrame)` - Raw frame received (if assembleFragments is false)
110
- `'close'` - `(reasonCode, description)` - Connection closed
111
- `'error'` - `(error)` - Connection error
112
- `'ping'` - `(cancel, data)` - Ping frame received
113
- `'pong'` - `(data)` - Pong frame received
114
- `'drain'` - Socket drain event (outgoing buffer emptied)
115
- `'pause'` - Socket pause event
116
- `'resume'` - Socket resume event
117
118
**Usage Example:**
119
120
```javascript
121
// Server-side: handling connection from request
122
wsServer.on('request', function(request) {
123
const connection = request.accept('echo-protocol', request.origin);
124
125
// Connection event handlers
126
connection.on('message', function(message) {
127
console.log('Received Message:', message.type);
128
129
if (message.type === 'utf8') {
130
console.log('UTF-8 Data: ' + message.utf8Data);
131
// Echo back
132
connection.sendUTF('Echo: ' + message.utf8Data);
133
} else if (message.type === 'binary') {
134
console.log('Binary Data: ' + message.binaryData.length + ' bytes');
135
// Echo back binary
136
connection.sendBytes(message.binaryData);
137
}
138
});
139
140
connection.on('ping', function(cancel, data) {
141
console.log('Received ping');
142
// Pong is sent automatically, but you can cancel it
143
// cancel.cancel = true;
144
});
145
146
connection.on('pong', function(data) {
147
console.log('Received pong');
148
});
149
150
connection.on('close', function(reasonCode, description) {
151
console.log('Connection closed: ' + reasonCode + ' - ' + description);
152
});
153
154
connection.on('error', function(error) {
155
console.log('Connection error: ' + error.toString());
156
});
157
158
// Send periodic pings
159
const pingInterval = setInterval(function() {
160
if (connection.connected) {
161
connection.ping(Buffer.from('ping-data'));
162
} else {
163
clearInterval(pingInterval);
164
}
165
}, 30000);
166
});
167
168
// Client-side: handling connection
169
client.on('connect', function(connection) {
170
// Send different types of data
171
connection.sendUTF('Hello Server!');
172
connection.sendBytes(Buffer.from([0x01, 0x02, 0x03, 0x04]));
173
174
// Auto-detect send method
175
connection.send('Text message'); // Uses sendUTF
176
connection.send(Buffer.from('Binary data')); // Uses sendBytes
177
178
// Handle responses
179
connection.on('message', function(message) {
180
if (message.type === 'utf8') {
181
console.log('Server says: ' + message.utf8Data);
182
}
183
});
184
185
// Graceful close after 5 seconds
186
setTimeout(function() {
187
connection.close(1000, 'Normal closure');
188
}, 5000);
189
});
190
```
191
192
### Message Processing
193
194
**Message Object Structure:**
195
196
```javascript { .api }
197
interface WebSocketMessage {
198
/** Message type: 'utf8' for text, 'binary' for binary data */
199
type: 'utf8' | 'binary';
200
201
/** UTF-8 string data (present when type is 'utf8') */
202
utf8Data?: string;
203
204
/** Binary data as Buffer (present when type is 'binary') */
205
binaryData?: Buffer;
206
}
207
```
208
209
**Message Handling Patterns:**
210
211
```javascript
212
connection.on('message', function(message) {
213
switch (message.type) {
214
case 'utf8':
215
// Handle text message
216
const textData = message.utf8Data;
217
console.log('Text:', textData);
218
219
// Parse JSON if applicable
220
try {
221
const jsonData = JSON.parse(textData);
222
handleJsonMessage(jsonData);
223
} catch (e) {
224
handleTextMessage(textData);
225
}
226
break;
227
228
case 'binary':
229
// Handle binary message
230
const binaryData = message.binaryData;
231
console.log('Binary length:', binaryData.length);
232
233
// Process binary data
234
if (binaryData.length > 0) {
235
const firstByte = binaryData[0];
236
console.log('First byte:', firstByte);
237
}
238
break;
239
}
240
});
241
```
242
243
### Connection State Management
244
245
**Connection States:**
246
247
- `'open'` - Connection is active and ready for communication
248
- `'peer_requested_close'` - Remote peer initiated close handshake
249
- `'ending'` - Local close initiated, waiting for peer response
250
- `'closed'` - Connection is fully closed
251
252
**State Monitoring:**
253
254
```javascript
255
connection.on('close', function(reasonCode, description) {
256
console.log('Connection state:', connection.state); // 'closed'
257
console.log('Close reason:', reasonCode, description);
258
console.log('Connected status:', connection.connected); // false
259
});
260
261
// Monitor state changes
262
const originalState = connection.state;
263
setInterval(function() {
264
if (connection.state !== originalState) {
265
console.log('State changed from', originalState, 'to', connection.state);
266
}
267
}, 1000);
268
```
269
270
### Error Handling and Recovery
271
272
**Error Types and Handling:**
273
274
```javascript
275
connection.on('error', function(error) {
276
console.error('WebSocket Error:', error.message);
277
278
// Check if connection is still viable
279
if (connection.connected) {
280
console.log('Connection still active, error was recoverable');
281
} else {
282
console.log('Connection lost due to error');
283
// Attempt reconnection logic here
284
attemptReconnection();
285
}
286
});
287
288
// Handle different types of errors
289
connection.on('error', function(error) {
290
if (error.code === 'ECONNRESET') {
291
console.log('Connection reset by peer');
292
} else if (error.code === 'ETIMEDOUT') {
293
console.log('Connection timed out');
294
} else {
295
console.log('Other error:', error.code, error.message);
296
}
297
});
298
```
299
300
### Flow Control
301
302
**Backpressure Handling:**
303
304
```javascript
305
// Monitor drain events for flow control
306
let canSendMore = true;
307
308
connection.on('drain', function() {
309
console.log('Output buffer drained, can send more data');
310
canSendMore = true;
311
// Resume sending queued messages
312
sendQueuedMessages();
313
});
314
315
function sendMessage(data) {
316
if (canSendMore && connection.connected) {
317
const result = connection.sendUTF(data, function(error) {
318
if (error) {
319
console.error('Send error:', error);
320
canSendMore = false;
321
}
322
});
323
324
// Check if we should pause sending
325
if (!result) {
326
canSendMore = false;
327
console.log('Output buffer full, waiting for drain');
328
}
329
} else {
330
// Queue message for later
331
messageQueue.push(data);
332
}
333
}
334
```
335
336
### Connection Close Handling
337
338
**Close Reason Constants:**
339
340
```javascript { .api }
341
// Close reason constants (accessible as WebSocketConnection static properties)
342
WebSocketConnection.CLOSE_REASON_NORMAL = 1000;
343
WebSocketConnection.CLOSE_REASON_GOING_AWAY = 1001;
344
WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR = 1002;
345
WebSocketConnection.CLOSE_REASON_UNPROCESSABLE_INPUT = 1003;
346
WebSocketConnection.CLOSE_REASON_RESERVED = 1004;
347
WebSocketConnection.CLOSE_REASON_NOT_PROVIDED = 1005;
348
WebSocketConnection.CLOSE_REASON_ABNORMAL = 1006;
349
WebSocketConnection.CLOSE_REASON_INVALID_DATA = 1007;
350
WebSocketConnection.CLOSE_REASON_POLICY_VIOLATION = 1008;
351
WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG = 1009;
352
WebSocketConnection.CLOSE_REASON_EXTENSION_REQUIRED = 1010;
353
WebSocketConnection.CLOSE_REASON_INTERNAL_SERVER_ERROR = 1011;
354
WebSocketConnection.CLOSE_REASON_TLS_HANDSHAKE_FAILED = 1015;
355
356
// Close descriptions mapping
357
WebSocketConnection.CLOSE_DESCRIPTIONS = {
358
1000: 'Normal connection closure',
359
1001: 'Remote end going away',
360
1002: 'Protocol error',
361
1003: 'Unprocessable input',
362
1004: 'Reserved',
363
1005: 'Reason not provided',
364
1006: 'Abnormal closure, no close frame',
365
1007: 'Invalid frame payload data',
366
1008: 'Policy violation',
367
1009: 'Message too big',
368
1010: 'Extension required',
369
1011: 'Internal server error',
370
1015: 'TLS handshake failed'
371
};
372
```
373
374
**Graceful Shutdown:**
375
376
```javascript
377
function gracefulShutdown(connection) {
378
if (connection.connected) {
379
// Send any final messages
380
connection.sendUTF(JSON.stringify({ type: 'goodbye' }));
381
382
// Initiate clean close
383
connection.close(WebSocketConnection.CLOSE_REASON_NORMAL, 'Server shutting down');
384
385
// Force close after timeout
386
setTimeout(function() {
387
if (connection.state !== 'closed') {
388
console.log('Forcing connection close');
389
connection.drop(WebSocketConnection.CLOSE_REASON_NORMAL, 'Timeout');
390
}
391
}, 5000);
392
}
393
}
394
395
// Handle different close scenarios
396
connection.on('close', function(reasonCode, description) {
397
switch (reasonCode) {
398
case WebSocketConnection.CLOSE_REASON_NORMAL:
399
console.log('Clean shutdown');
400
break;
401
case WebSocketConnection.CLOSE_REASON_GOING_AWAY:
402
console.log('Peer is going away');
403
break;
404
case WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR:
405
console.log('Protocol error occurred');
406
break;
407
default:
408
console.log('Connection closed with code:', reasonCode);
409
}
410
});
411
```
412
413
## Types
414
415
### Connection Configuration
416
417
```javascript { .api }
418
interface ConnectionConfig {
419
maxReceivedFrameSize?: number;
420
maxReceivedMessageSize?: number;
421
fragmentOutgoingMessages?: boolean;
422
fragmentationThreshold?: number;
423
assembleFragments?: boolean;
424
disableNagleAlgorithm?: boolean;
425
closeTimeout?: number;
426
}
427
```
428
429
### Connection States
430
431
```javascript { .api }
432
type ConnectionState = 'open' | 'peer_requested_close' | 'ending' | 'closed';
433
```