乐闻世界logo
搜索文章和话题

How to implement WebSocket reconnection?

2月18日 22:08

WebSocket Reconnection Mechanism Explained

WebSocket connections may disconnect due to network fluctuations, server restarts, timeouts, etc. Implementing a reliable reconnection mechanism is crucial.

Connection State Detection

WebSocket has four connection states:

javascript
const ws = new WebSocket('ws://example.com'); // 0: CONNECTING - Connecting // 1: OPEN - Connected // 2: CLOSING - Closing // 3: CLOSED - Closed console.log(ws.readyState); // Get current state

Basic Reconnection Implementation

javascript
class WebSocketManager { constructor(url) { this.url = url; this.ws = null; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.reconnectInterval = 3000; // 3 seconds this.shouldReconnect = true; this.connect(); } connect() { this.ws = new WebSocket(this.url); this.ws.onopen = () => { console.log('WebSocket connection established'); this.reconnectAttempts = 0; }; this.ws.onclose = (event) => { console.log('WebSocket connection closed:', event.code, event.reason); if (this.shouldReconnect) { this.reconnect(); } }; this.ws.onerror = (error) => { console.error('WebSocket error:', error); }; } reconnect() { if (this.reconnectAttempts >= this.maxReconnectAttempts) { console.error('Max reconnection attempts reached, stop reconnecting'); return; } this.reconnectAttempts++; const delay = this.getReconnectDelay(); console.log(`Attempting ${this.reconnectAttempts}th reconnection after ${delay}ms`); setTimeout(() => { this.connect(); }, delay); } getReconnectDelay() { // Exponential backoff strategy return Math.min( this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1), 30000 // Max 30 seconds ); } disconnect() { this.shouldReconnect = false; if (this.ws) { this.ws.close(); } } } // Usage example const wsManager = new WebSocketManager('ws://example.com/socket');

Graceful Close Handling

javascript
class WebSocketManager { // ... other code close(code = 1000, reason = 'Normal closure') { this.shouldReconnect = false; if (this.ws && this.ws.readyState === WebSocket.OPEN) { this.ws.close(code, reason); } } // Determine if it's a normal close in onclose ws.onclose = (event) => { // Normal close status code: 1000 if (event.code === 1000) { console.log('Normal connection close'); return; } // Abnormal close, try to reconnect if (this.shouldReconnect) { this.reconnect(); } }; }

Common Close Status Codes

Status CodeMeaning
1000Normal closure
1001Endpoint going away
1002Protocol error
1003Unsupported data type
1005No status code (internal use)
1006Connection closed abnormally
1007Data type inconsistency
1008Policy violation
1009Message too large
1010Missing extension
1011Internal error
1015TLS handshake failure

Heartbeat Detection and Reconnection

javascript
class WebSocketManager { constructor(url) { // ... other initialization this.heartbeatInterval = 30000; // 30 seconds this.heartbeatTimer = null; this.pongTimeout = 5000; // 5 second timeout this.pongTimer = null; } startHeartbeat() { this.heartbeatTimer = setInterval(() => { if (this.ws && this.ws.readyState === WebSocket.OPEN) { this.sendPing(); } }, this.heartbeatInterval); } sendPing() { this.ws.send(JSON.stringify({ type: 'ping' })); // Set pong timeout this.pongTimer = setTimeout(() => { console.error('Heartbeat timeout, closing connection'); this.ws.close(); }, this.pongTimeout); } handlePong() { if (this.pongTimer) { clearTimeout(this.pongTimer); this.pongTimer = null; } } ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'pong') { this.handlePong(); } // Handle other messages... }; ws.onopen = () => { this.startHeartbeat(); }; ws.onclose = () => { this.stopHeartbeat(); }; stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } if (this.pongTimer) { clearTimeout(this.pongTimer); this.pongTimer = null; } } }

Offline Detection

javascript
class WebSocketManager { constructor(url) { // ... other initialization this.setupOfflineDetection(); } setupOfflineDetection() { window.addEventListener('online', () => { console.log('Network recovered, attempting to reconnect'); if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { this.connect(); } }); window.addEventListener('offline', () => { console.log('Network disconnected'); }); } }

Best Practices

  1. Exponential Backoff: Gradually increase reconnection interval to avoid server pressure
  2. Max Reconnection Attempts: Prevent infinite reconnection
  3. Heartbeat Mechanism: Timely detect connection status
  4. Graceful Close: Distinguish between normal and abnormal closure
  5. Offline Detection: Listen for network state changes
  6. Status Notification: Provide connection status feedback to users
  7. Message Queue: Cache messages during reconnection, send after connection succeeds
标签:WebSocket