- 🔌 Node.js Socket.IO Mastery 🚀
- Real-Time Communication Learning Project
- 📋 Table of Contents
- 🎯 Project Overview
- ✨ Features
- 🏗️ Architecture
- 🛠️ Tech Stack
- 📁 Project Structure
- 🚀 Getting Started
- 🔌 Socket.IO Concepts Covered
- 📡 Event Flow
- 🎨 Client Features
- 🖥️ Server Features
- 📊 Example Usage
- 🔧 Configuration
- 🧪 Testing
- 🐛 Troubleshooting
- 📈 Performance Considerations
- 🔮 Advanced Topics to Explore
- 📚 Learning Resources
- 👨💻 Author
- 📄 License
- 🙏 Acknowledgments
This project is a comprehensive learning exploration of Socket.IO, the leading library for real-time, bidirectional, event-based communication between web clients and servers. Built from scratch, it demonstrates how to create interactive applications with persistent connections, real-time data exchange, and instant event handling.
| Feature | Traditional HTTP | Socket.IO |
|---|---|---|
| Connection | Request-response, stateless | Persistent, stateful |
| Communication | One-way (client → server) | Bidirectional (client ↔ server) |
| Real-time | Polling required | Native real-time |
| Overhead | High per request | Low per message |
| Latency | High (new connection each time) | Low (persistent connection) |
| Use Cases | REST APIs, page loads | Chat, gaming, live updates |
| Category | Feature | Status |
|---|---|---|
| Connection Management | Real-time persistent connections | ✅ |
| Event System | Custom event emission and handling | ✅ |
| Message Broadcasting | Send messages to all connected clients | ✅ |
| Room Management | Group clients into logical rooms | ✅ |
| Namespace Support | Isolated communication channels | ✅ |
| Disconnect Handling | Automatic cleanup on client disconnect | ✅ |
| Error Recovery | Automatic reconnection with backoff | ✅ |
| Multiple Clients | Handle concurrent connections | ✅ |
| Server Events | Emit events from server to clients | ✅ |
| Client Events | Emit events from clients to server | ✅ |
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER (Browser) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Socket.IO Client Library │ │
│ │ • Establishes WebSocket connection │ │
│ │ • Manages reconnection logic │ │
│ │ • Emits and listens to events │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ UI Components │ │
│ │ • Event displays │ │
│ │ • Message input forms │ │
│ │ • Connection status indicators │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────┬───────────────────────────────────────────┘
│
WebSocket / HTTP Long-Polling
│
┌─────────────────────────────────┴───────────────────────────────────────────┐
│ SERVER LAYER (Node.js) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ HTTP Server │ │
│ │ • Serves static files (HTML, CSS, JS) │ │
│ │ • Handles initial page loads │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Socket.IO Server │ │
│ │ • Manages all client connections │ │
│ │ • Handles event routing │ │
│ │ • Manages rooms and namespaces │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Event Handlers │ │
│ │ • connection: New client joined │ │
│ │ • message: User sent message │ │
│ │ • disconnect: Client left │ │
│ │ • custom-event: Application-specific logic │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘| Technology | Version | Purpose | Badge |
|---|---|---|---|
| Node.js | 18+ | JavaScript Runtime | |
| Express.js | 4.x | Web Framework | |
| Socket.IO | 4.x | Real-time Engine | |
| HTML5 | - | Structure | |
| JavaScript | ES6+ | Client Logic |
node-socket.io/
│
├── 📁 client/ # Frontend application
│ ├── 📄 index.html # Main UI page
│ ├── 📄 script.js # Active client logic
│ ├── 📄 script_0.js # Learning iteration 0
│ ├── 📄 script_1.js # Learning iteration 1
│ ├── 📄 package.json # Client dependencies
│ └── 📄 package-lock.json # Locked dependencies
│
├── 📁 server/ # Backend application
│ ├── 📄 server.js # Active server logic
│ ├── 📄 server_0.js # Learning iteration 0
│ ├── 📄 server_1.js # Learning iteration 1
│ ├── 📄 server_2.js # Learning iteration 2
│ ├── 📄 package.json # Server dependencies
│ └── 📄 package-lock.json # Locked dependencies
│
├── 📄 .gitignore # Git ignore rules
└── 📄 README.md # Documentation| File | Topic Covered |
|---|---|
server_0.js / script_0.js |
Basic connection establishment |
server_1.js / script_1.js |
Event emission and handling |
server_2.js / script_2.js |
Broadcasting and rooms |
- ✅ Node.js (v18 or higher)
- ✅ npm or yarn package manager
- ✅ Modern web browser (Chrome, Firefox, Edge)
# 1. Clone the repository
git clone https://github.com/elyse502/node-socket.io.git
# 2. Navigate to project directory
cd node-socket.io
# 3. Install server dependencies
cd server
npm install
# 4. Install client dependencies (if any)
cd ../client
npm install
# 5. Return to root directory
cd ..# Start the server (from server directory)
cd server
npm run devStart
# OR for development with auto-reload
nodemon server.js
# Open browser and navigate to
http://localhost:3000# Development mode (with auto-restart)
npm run dev
# Production mode
npm start
# Alternative port (modify server.js)
PORT=8080 npm start// Server
const io = require("socket.io")(server);
io.on("connection", (socket) => {
console.log("New client connected:", socket.id);
});
// Client
const socket = io("http://localhost:3000");
socket.on("connect", () => {
console.log("Connected to server");
});// Client to Server
socket.emit("message", { text: "Hello Server!" });
// Server to Client
socket.emit("welcome", { message: "Welcome to the chat!" });
// Server to All Clients (Broadcast)
io.emit("announcement", { text: "New user joined!" });// Server
socket.on("message", (data) => {
console.log("Received:", data);
// Process and possibly respond
});
// Client
socket.on("welcome", (data) => {
console.log("Server says:", data.message);
});// Server
socket.on("disconnect", (reason) => {
console.log("Client disconnected:", socket.id, "Reason:", reason);
});
// Client
socket.on("disconnect", (reason) => {
console.log("Disconnected from server:", reason);
});// Send to all clients except sender
socket.broadcast.emit("user-joined", { userId: socket.id });
// Send to all clients including sender
io.emit("global-update", { status: "active" });
// Send to specific room
io.to("room1").emit("room-message", { text: "Hello Room 1!" });┌──────────┐ ┌──────────┐
│ Client │ │ Server │
│ A │ │ │
└────┬─────┘ └────┬─────┘
│ │
│ 1. socket.emit('message', data) │
│──────────────────────────────────────────────>│
│ │
│ │ 2. Process message
│ │ Save to DB
│ │ Broadcast to others
│ │
│ 3. socket.broadcast.emit('message', data) │
│<──────────────────────────────────────────────│
│ │
│ 4. socket.on('message', handler) │
│ Display message │
│ │
│ 5. User disconnects │
│──────────────────────────────────────────────>│
│ │
│ 6. io.emit('user-left', userId) │
│<──────────────────────────────────────────────│
│ │
│ 7. Update UI - remove user │
│ │
// Monitor connection state
socket.on("connect", () => {
updateStatus("Connected", "green");
});
socket.on("disconnect", () => {
updateStatus("Disconnected", "red");
});
socket.on("connect_error", (error) => {
updateStatus("Connection Error", "orange");
});// Socket.IO handles reconnection automatically
// Configure reconnection options
const socket = io({
reconnection: true,
reconnectionAttempts: 5,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
});<!-- Sample HTML Structure -->
<div id="messages">
<div class="message received">
<strong>User:</strong> Hello!
<small>10:30 AM</small>
</div>
</div>
<input type="text" id="messageInput" placeholder="Type a message..." />
<button onclick="sendMessage()">Send</button>const io = require("socket.io")(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"],
},
});
// Track connected users
const users = new Map();
io.on("connection", (socket) => {
users.set(socket.id, { id: socket.id, joinedAt: Date.now() });
console.log(`Total users: ${users.size}`);
socket.on("disconnect", () => {
users.delete(socket.id);
console.log(`Total users: ${users.size}`);
});
});// Join a room
socket.on("join-room", (roomName) => {
socket.join(roomName);
socket.to(roomName).emit("user-joined", socket.id);
});
// Leave a room
socket.on("leave-room", (roomName) => {
socket.leave(roomName);
socket.to(roomName).emit("user-left", socket.id);
});
// Send to room
socket.to("chat-room").emit("message", data);Server (server.js):
const express = require("express");
const http = require("http");
const socketIo = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
app.use(express.static("client"));
io.on("connection", (socket) => {
console.log("User connected:", socket.id);
// Broadcast to others that user joined
socket.broadcast.emit("user-joined", socket.id);
// Handle incoming messages
socket.on("chat-message", (message) => {
// Broadcast message to all clients
io.emit("chat-message", {
userId: socket.id,
text: message,
timestamp: new Date().toISOString(),
});
});
socket.on("disconnect", () => {
console.log("User disconnected:", socket.id);
io.emit("user-left", socket.id);
});
});
server.listen(3000, () => {
console.log("Server running on port 3000");
});Client (script.js):
const socket = io();
// DOM elements
const messageForm = document.getElementById("message-form");
const messageInput = document.getElementById("message-input");
const messagesDiv = document.getElementById("messages");
// Send message
messageForm.addEventListener("submit", (e) => {
e.preventDefault();
const message = messageInput.value;
if (message) {
socket.emit("chat-message", message);
messageInput.value = "";
}
});
// Receive message
socket.on("chat-message", (data) => {
const messageElement = document.createElement("div");
messageElement.className = "message";
messageElement.innerHTML = `
<strong>${data.userId}</strong>
<span>${data.text}</span>
<small>${new Date(data.timestamp).toLocaleTimeString()}</small>
`;
messagesDiv.appendChild(messageElement);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
});
// User joined/left notifications
socket.on("user-joined", (userId) => {
addSystemMessage(`User ${userId} joined the chat`);
});
socket.on("user-left", (userId) => {
addSystemMessage(`User ${userId} left the chat`);
});const io = socketIo(server, {
// CORS settings
cors: {
origin: "*",
methods: ["GET", "POST"],
credentials: true,
},
// Transport options
transports: ["websocket", "polling"],
// Connection options
pingTimeout: 60000,
pingInterval: 25000,
// Upgrade options
allowUpgrades: true,
upgradeTimeout: 10000,
// Cookie options
cookie: {
name: "io",
httpOnly: true,
sameSite: "lax",
},
});const socket = io({
// Connection URL
path: "/socket.io",
// Transport options
transports: ["websocket", "polling"],
// Reconnection options
reconnection: true,
reconnectionAttempts: Infinity,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
// Timeout options
timeout: 20000,
// Query parameters
query: {
token: "your-auth-token",
userId: "123",
},
// Authentication
auth: {
token: "your-jwt-token",
},
});# Terminal 1 - Start server
cd server
npm run devStart
# Terminal 2 - Open first client
open http://localhost:3000
# Terminal 3 - Open second client (incognito/private window)
open http://localhost:3000# Use wscat for WebSocket testing
npm install -g wscat
wscat -c ws://localhost:3000/socket.io/?EIO=4&transport=websocket// Enable debug logging
localStorage.debug = 'socket.io-client:*';
// Or in Node.js
DEBUG=socket.io:* node server.js| Issue | Solution |
|---|---|
| Connection refused | Check if server is running on correct port |
| CORS errors | Configure CORS options in server |
| Connection drops | Increase pingTimeout and pingInterval |
| Messages not received | Check event names match exactly |
| Multiple connections | Ensure socket.io client imported only once |
| Reconnection not working | Check reconnection options configuration |
| Large messages failing | Implement message chunking or increase limits |
| Aspect | Recommendation | Why |
|---|---|---|
| Message Size | Keep < 10KB | Large messages fragment and increase latency |
| Event Frequency | Limit to < 100/sec | Too many events overwhelm the connection |
| Connected Clients | Scale horizontally | Single server handles ~10,000 connections |
| Rooms | Clean up empty rooms | Prevents memory leaks |
| Binary Data | Use binary transfers | More efficient for images/files |
| Compression | Enable per-message deflate | Reduces bandwidth usage |
// Use Redis adapter for multiple server instances
const redisAdapter = require("@socket.io/redis-adapter");
const redis = require("redis");
const pubClient = redis.createClient();
const subClient = pubClient.duplicate();
io.adapter(redisAdapter(pubClient, subClient));| Topic | Description | Difficulty |
|---|---|---|
| Namespaces | Separate communication channels | ⭐⭐ |
| Rooms | Group-based messaging | ⭐⭐ |
| Acknowledgements | Confirmation of message receipt | ⭐⭐⭐ |
| Middleware | Authentication and logging | ⭐⭐⭐ |
| Redis Adapter | Horizontal scaling | ⭐⭐⭐⭐ |
| Binary Streaming | File and data streaming | ⭐⭐⭐⭐ |
| Custom Parsers | Optimize data serialization | ⭐⭐⭐⭐⭐ |
- Week 1: Basic connections and events
- Week 2: Broadcasting and rooms
- Week 3: Error handling and reconnection
- Week 4: Building a complete chat application
- Week 5: Advanced features (acknowledgements, middleware)
- Week 6: Scaling with Redis and production deployment
Junior Fullstack Software Engineer
This project is licensed under the MIT License - see the LICENSE file for details.
- Socket.IO Team - For the amazing real-time library
- Node.js Community - For continuous support
- Open Source Contributors - For making real-time web accessible
Built with 💻, WebSockets, and Real-Time Passion
From basic connections to production-ready real-time applications - this is your complete Socket.IO learning journey!