What are WebSockets?
Full-dupex communication channel over a single TCP connection.
WebSocket vs HTTP
HTTP:
- Request-Response
- Stateless
- One-way communication
- Overhead per request
WebSocket:
- Persistent connection
- Stateful
- Bidirectional communication
- Low latencyClient-Side WebSocket API
javascript
// Create WebSocket connection
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', (event) => {
console.log('Connected to server');
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', (event) => {
console.log('Message from server:', event.data);
});
// Connection closed
socket.addEventListener('close', (event) => {
console.log('Disconnected from server');
});
// Error handling
socket.addEventListener('error', (event) => {
console.error('WebSocket error:', event);
});React Hook
javascript
import { useEffect, useState } from 'react';
function useWebSocket(url) {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState([]);
const [connected, setConnected] = useState(false);
useEffect(() => {
const ws = new WebSocket(url);
ws.onopen = () => {
setConnected(true);
setSocket(ws);
};
ws.onmessage = (event) => {
setMessages(prev => [...prev, event.data]);
};
ws.onclose = () => {
setConnected(false);
};
return () => {
ws.close();
};
}, [url]);
const sendMessage = (message) => {
if (socket && connected) {
socket.send(message);
}
};
return { messages, sendMessage, connected };
}
// Usage
function Chat() {
const { messages, sendMessage, connected } = useWebSocket('ws://localhost:8080');
return (
<div>
<p>Status: {connected ? 'Connected' : 'Disconnected'}</p>
<ul>
{messages.map((msg, i) => <li key={i}>{msg}</li>)}
</ul>
<button onClick={() => sendMessage('Hello')}>Send</button>
</div>
);
}Server-Side (Node.js)
javascript
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
const clients = new Set();
wss.on('connection', (ws) => {
console.log('New client connected');
clients.add(ws);
// Send welcome message
ws.send('Welcome to the server!');
// Handle incoming messages
ws.on('message', (message) => {
console.log('Received:', message.toString());
// Broadcast to all clients
clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
// Handle disconnect
ws.on('close', () => {
console.log('Client disconnected');
clients.delete(ws);
});
// Handle errors
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
});
console.log('WebSocket server running on ws://localhost:8080');Socket.io (Simplified WebSockets)
Server
javascript
import { Server } from 'socket.io';
const io = new Server(3000);
io.on('connection', (socket) => {
console.log('User connected:', socket.id);
// Join room
socket.on('join-room', (room) => {
socket.join(room);
socket.to(room).emit('user-joined', socket.id);
});
// Handle messages
socket.on('message', (data) => {
io.to(data.room).emit('message', {
user: socket.id,
text: data.text
});
});
// Handle disconnect
socket.on('disconnect', () => {
console.log('User disconnected:', socket.id);
});
});Client
javascript
import io from 'socket.io-client';
const socket = io('http://localhost:3000');
// Join room
socket.emit('join-room', 'chat-room');
// Send message
socket.emit('message', {
room: 'chat-room',
text: 'Hello!'
});
// Listen for messages
socket.on('message', (data) => {
console.log(data.user, data.text);
});Authentication
javascript
// Server: Authenticate connection
wss.on('connection', (ws, req) => {
const token = new URL(req.url, 'http://localhost').searchParams.get('token');
try {
const decoded = jwt.verify(token, SECRET);
ws.userId = decoded.userId;
} catch (error) {
ws.close(4001, 'Unauthorized');
}
});Reconnection Strategy
javascript
class ReconnectingWebSocket {
constructor(url) {
this.url = url;
this.reconnectDelay = 1000;
this.maxReconnectDelay = 30000;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('Connected');
this.reconnectDelay = 1000; // Reset
};
this.ws.onclose = () => {
console.log('Disconnected, reconnecting...');
setTimeout(() => {
this.connect();
}, this.reconnectDelay);
this.reconnectDelay = Math.min(
this.reconnectDelay * 2,
this.maxReconnectDelay
);
};
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(data);
}
}
}Use Cases
- Chat applications: Real-time messaging
- Live updates: Stock prices, sports scores
- Collaboration: Google Docs-like editing
- Gaming: Multiplayer games
- Notifications: Push notifications
Real-time is the future!