🏠 Home / Hub

🟢 Node.js Lesson 08 — WebSockets & Socket.io

← Back to Node.js Menu  |  🏠 Hub

1. HTTP vs WebSocket

FeatureHTTPWebSocket
ConnectionRequest → Response → ClosePersistent, open both ways
DirectionClient → Server onlyBoth directions simultaneously
Real-timePolling needed (inefficient)Native push from server
Use casesCRUD, REST APIsChat, live updates, gaming, stocks
ProtocolHTTP/HTTPSWS/WSS (ws:// wss://)

2. Socket.io Setup

# Install
npm install socket.io express

# Server: server.js
const express = require('express');
const http    = require('http');
const { Server } = require('socket.io');

const app    = express();
const server = http.createServer(app);    // wrap express
const io     = new Server(server, {
  cors: {
    origin: "*",           // allow all origins (dev only!)
    methods: ["GET", "POST"]
  }
});

app.use(express.static('public'));  // serve client HTML

// Socket.io connection
io.on('connection', (socket) => {
  console.log('User connected:', socket.id);

  // Listen for events from client
  socket.on('message', (data) => {
    console.log('Received:', data);
    // Broadcast to all clients
    io.emit('message', data);
  });

  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

server.listen(3000, () => console.log('Server running on :3000'));

3. Complete Chat App

// server.js — Chat server
const express = require('express');
const http    = require('http');
const { Server } = require('socket.io');

const app    = express();
const server = http.createServer(app);
const io     = new Server(server);

const users   = new Map();   // socket.id → username
const history = [];          // last 50 messages

app.use(express.static('public'));

io.on('connection', (socket) => {
  // User joins
  socket.on('join', (username) => {
    users.set(socket.id, username);

    // Send history to new user
    socket.emit('history', history);

    // Notify others
    socket.broadcast.emit('system', `${username} joined the chat`);
    io.emit('users', Array.from(users.values()));
    console.log(`${username} joined`);
  });

  // Chat message
  socket.on('chat', (text) => {
    const username = users.get(socket.id) || 'Anonymous';
    const msg = {
      id:       Date.now(),
      username,
      text,
      time:     new Date().toLocaleTimeString(),
    };

    history.push(msg);
    if (history.length > 50) history.shift();  // keep last 50

    io.emit('chat', msg);  // broadcast to ALL
  });

  // Typing indicator
  socket.on('typing', (isTyping) => {
    const username = users.get(socket.id);
    socket.broadcast.emit('typing', { username, isTyping });
  });

  // Room support
  socket.on('joinRoom', (room) => {
    socket.join(room);
    io.to(room).emit('system', `${users.get(socket.id)} joined room: ${room}`);
  });

  socket.on('roomMessage', ({ room, text }) => {
    const msg = { username: users.get(socket.id), text, time: new Date().toLocaleTimeString() };
    io.to(room).emit('roomChat', msg);  // only this room!
  });

  // Disconnect
  socket.on('disconnect', () => {
    const username = users.get(socket.id);
    users.delete(socket.id);
    if (username) {
      io.emit('system', `${username} left`);
      io.emit('users', Array.from(users.values()));
    }
  });
});

server.listen(3000);

4. Client-Side (public/index.html)

<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>Chat</title>
  <script src="/socket.io/socket.io.js"></script>
</head>
<body>
  <div id="messages"></div>
  <input id="msg" placeholder="Type message...">
  <button onclick="send()">Send</button>

  <script>
    const socket = io();   // auto-connect to server
    const name   = prompt("Your name:");

    socket.emit('join', name);

    // Receive history
    socket.on('history', (msgs) => {
      msgs.forEach(addMessage);
    });

    // Receive chat
    socket.on('chat', addMessage);

    // System messages
    socket.on('system', (msg) => {
      const el = document.createElement('p');
      el.style.color = 'gray';
      el.textContent = msg;
      document.getElementById('messages').appendChild(el);
    });

    // Typing indicator
    const input = document.getElementById('msg');
    input.addEventListener('input', () => {
      socket.emit('typing', input.value.length > 0);
    });

    socket.on('typing', ({ username, isTyping }) => {
      // show/hide "Ko Ko is typing..."
    });

    function send() {
      const text = input.value.trim();
      if (text) {
        socket.emit('chat', text);
        input.value = '';
      }
    }

    function addMessage(msg) {
      const el = document.createElement('p');
      el.innerHTML = `<strong>${msg.username}</strong> [${msg.time}]: ${msg.text}`;
      document.getElementById('messages').appendChild(el);
    }

    input.addEventListener('keydown', e => { if (e.key === 'Enter') send(); });
  </script>
</body>
</html>

5. Socket.io Emit Cheat Sheet

MethodSends To
socket.emit('event', data)This socket only (one client)
io.emit('event', data)ALL connected clients
socket.broadcast.emit('event', data)All EXCEPT this socket
io.to(room).emit('event', data)Everyone in a room
socket.to(room).emit('event', data)Room, except sender
socket.join(room)Join a room
socket.leave(room)Leave a room

← Node.js 07  |  Next: Node.js 09 → Testing →

📌 Study Checklist