Episode 3 of 5

Using Socket.io

Integrate Socket.io with your Express app — set up the server, connect the client, and establish your first real-time connection.

Using Socket.io

Now that we have an Express server, it is time to add Socket.io and establish a real-time connection between the server and the browser. In this episode you will install Socket.io, integrate it with Express, and connect the client to the server.

Step 1: Install Socket.io

npm install socket.io

This installs the Socket.io server library. The client library is automatically served by the Socket.io server — you do not need to install it separately.

Step 2: Integrate Socket.io with Express

Update your index.js to use Socket.io:

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);

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

// Listen for client connections
io.on('connection', (socket) => {
    console.log('A user connected:', socket.id);

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

const PORT = 3000;
server.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});

What Changed?

BeforeAfterWhy
app.listen()server.listen()Socket.io needs the raw HTTP server, not the Express app
No http modulehttp.createServer(app)Creates an HTTP server that Express and Socket.io share
No socket.ionew Server(server)Attaches Socket.io to the HTTP server

The key change is that we create the HTTP server manually with http.createServer(app) and pass it to both Socket.io and Express. Previously, app.listen() created the HTTP server internally — now we need direct access to it.

Understanding the Server Code

io.on('connection', (socket) => {
    console.log('A user connected:', socket.id);
});

The io.on('connection') event fires every time a client connects. The socket parameter represents that specific client's connection. Each socket has a unique id that identifies the connection.

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

The disconnect event fires when a client loses connection — closing the tab, navigating away, or losing network connectivity.

Step 3: Connect the Client

Update your public/index.html to include the Socket.io client library and connect to the server. Add this before the closing </body> tag:

<script src="/socket.io/socket.io.js"></script>
<script>
    const socket = io();

    socket.on('connect', () => {
        console.log('Connected to server with ID:', socket.id);
    });

    socket.on('disconnect', () => {
        console.log('Disconnected from server');
    });
</script>

How the Client Library Works

LineWhat It Does
/socket.io/socket.io.jsSocket.io server automatically serves its client library at this URL
io()Connects to the Socket.io server that served the page (auto-detects the URL)
socket.on('connect')Fires when the connection is established successfully
socket.on('disconnect')Fires when the connection is lost

You do not need to specify the server URL in io() — it automatically connects to the server that served the page. If you needed to connect to a different server, you would pass the URL: io('http://other-server:3000').

Step 4: Test the Connection

node index.js

Open http://localhost:3000 in your browser. In the terminal, you should see:

Server running on http://localhost:3000
A user connected: abc123xyz

Open the browser console (F12 → Console tab) and you should see:

Connected to server with ID: abc123xyz

If you close the browser tab, the terminal shows:

User disconnected: abc123xyz

Testing Multiple Connections

Open multiple browser tabs pointing to http://localhost:3000. Each tab creates a new socket connection with a unique ID. The server will log each connection separately. This demonstrates that Socket.io handles multiple simultaneous connections automatically.

How Socket.io Connects Under the Hood

1. Browser loads the page from Express (HTTP GET /)
2. Browser loads Socket.io client library (/socket.io/socket.io.js)
3. Client calls io() which sends an HTTP request with upgrade headers
4. Server responds with 101 Switching Protocols
5. Connection upgrades to WebSocket
6. Both sides can now emit events freely
7. Socket.io maintains the connection with heartbeats (ping/pong)

Socket.io also sends periodic "ping" messages to check if the connection is still alive. If the server does not receive a "pong" response, it considers the client disconnected.

Key Takeaways

  • Socket.io requires the raw HTTP server — use http.createServer(app) instead of app.listen()
  • The Socket.io server automatically serves its client library at /socket.io/socket.io.js
  • Calling io() on the client automatically connects to the server that served the page
  • Each connected client gets a unique socket.id for identification
  • io.on('connection') fires on the server for every new client connection
  • Socket.io handles reconnection, heartbeats, and transport fallback automatically