WebSockets & Socket.io
Overview
HTTP is strictly Unidirectional and Stateless. The client must explicitly ask for data, and the server answers. The server CANNOT initiate a conversation (it cannot push a chat message to a user who hasn't asked for it). Historically, developers used 'Long Polling' (asking the server 'Any new messages?' every 1 second), which destroyed performance. WebSockets are a completely different protocol (ws://). It upgrades the HTTP handshake into a persistent, Bi-Directional, open TCP pipe. Both the server and the client can push data to each other instantly, enabling real-time chat, live notifications, and multiplayer games. Socket.io is the industry-standard wrapper for WebSockets in Node.
Syntax
// npm install socket.io
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
// You MUST extract the raw HTTP server to bind WebSockets to it!
const server = http.createServer(app);
const io = new Server(server, { cors: { origin: '*' } });
// Listen for new WebSocket connections
io.on('connection', (socket) => {
console.log(`User connected: ${socket.id}`);
// 1. Listen for a specific event FROM the client
socket.on('send_message', (payload) => {
// 2. Broadcast that exact message to EVERY OTHER connected user!
// (Perfect for global chat rooms)
socket.broadcast.emit('receive_message', payload);
});
// Handle disconnections safely
socket.on('disconnect', () => {
console.log(`User left: ${socket.id}`);
});
});
// CRITICAL: Start the raw server, NOT the Express app!
server.listen(3000);Common Pitfalls
- Scaling WebSockets across multiple servers. If User A is connected to Node Server 1, and User B is connected to Node Server 2, and User A sends a chat message, Server 1 does not know how to tell Server 2 to update User B! You MUST configure a 'Pub/Sub Adapter' (like the Redis Adapter for Socket.io) to synchronize WebSocket events across the entire server cluster.
- Failing to authenticate the WebSocket upgrade. A WebSocket connection bypasses standard Express middleware! If you just accept all connections, hackers can connect directly to your socket port. You must implement specific Socket.io middleware (
io.use()) to verify JWT tokens during the initial handshake.
Interview Questions
io.emit(), socket.emit(), and socket.broadcast.emit()?io.emit() blasts the data to absolutely every single user connected to the server. socket.emit() sends data privately, only back to the specific user who triggered the event. socket.broadcast.emit() sends the data to everyone ELSE, explicitly excluding the user who sent it.
Real-World Example
Using Socket.io 'Rooms' to isolate real-time data to specific groups (like a private Slack channel or a Discord server).
io.on('connection', (socket) => {
// The user requests to join a specific private room
socket.on('join_room', (roomId) => {
socket.join(roomId); // Native Socket.io magic!
});
socket.on('private_message', (data) => {
// Blasts the message ONLY to users inside that specific room!
io.to(data.roomId).emit('new_message', data.text);
});
});Check Your Knowledge
Test your understanding of WebSockets & Socket.io with these quick questions.