PureTools

WebSockets: Real-Time Communication for the Web

PureTools Team· 7 min read
WebSockets: Real-Time Communication for the Web

WebSockets: When HTTP Isn't Enough

HTTP is request-response: the client asks, the server answers. But for real-time features — chat, live notifications, collaborative editing, live dashboards — you need the server to push data to the client without being asked. That's WebSockets.

HTTP vs WebSocket

FeatureHTTPWebSocket
CommunicationRequest → ResponseBidirectional
ConnectionNew connection per requestPersistent connection
OverheadHeaders on every requestMinimal after handshake
Server pushNot native (polling, SSE)Native
ProtocolHTTP/1.1, HTTP/2ws:// or wss://

The Handshake

// Client sends HTTP upgrade request
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

// Server responds
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

// Now both sides can send messages freely

Browser API

const ws = new WebSocket('wss://example.com/chat');

ws.onopen = () => {
  console.log('Connected');
  ws.send(JSON.stringify({ type: 'join', room: 'general' }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};

ws.onclose = (event) => {
  console.log('Disconnected:', event.code, event.reason);
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

Server Implementation (Node.js)

// Using the 'ws' library
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('Client connected');

  ws.on('message', (data) => {
    const message = JSON.parse(data);
    
    // Broadcast to all clients
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(message));
      }
    });
  });

  ws.on('close', () => {
    console.log('Client disconnected');
  });
});

Socket.IO (Batteries Included)

// Server
import { Server } from 'socket.io';
const io = new Server(3000, { cors: { origin: '*' } });

io.on('connection', (socket) => {
  socket.join('room:general');
  
  socket.on('chat:message', (msg) => {
    io.to('room:general').emit('chat:message', {
      user: socket.id,
      text: msg,
      timestamp: Date.now(),
    });
  });
});

// Client
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000');

socket.on('chat:message', (msg) => {
  console.log(msg);
});

socket.emit('chat:message', 'Hello!');

When to Use What

TechniqueBest ForComplexity
WebSocketChat, gaming, live collaborationMedium
SSE (Server-Sent Events)One-way server → client (notifications, feeds)Low
HTTP PollingSimple status checks, low frequencyLowest
HTTP Long PollingFallback when WebSocket/SSE unavailableLow

If the client only needs to receive updates (not send), consider SSE — it's simpler, works over HTTP, and auto-reconnects.

Test your APIs: HTTP Reference — status codes and headers reference.