tests.ws

WebSocket Examples and Use Cases

websocket examples use-cases real-time applications

WebSocket examples demonstrate the protocol’s power for building real-time applications. Whether you’re developing a chat app, live dashboard, multiplayer game, or collaborative editor, understanding practical websocket application patterns helps you leverage websocket communication effectively. This guide explores real-world websocket use cases with code samples showing how to use websocket connections for bidirectional data exchange.

Real-Time Chat Application

Chat applications represent the classic websocket example. Unlike HTTP polling, WebSocket enables instant message delivery with minimal overhead, making it ideal for websocket app development requiring real-time communication.

Client-Side Chat Implementation

class ChatClient {
  constructor(username) {
    this.username = username;
    this.ws = null;
    this.messageHandlers = [];
  }

  connect(url) {
    this.ws = new WebSocket(url);

    this.ws.onopen = () => {
      console.log('Connected to chat server');
      // Send join message
      this.send({
        type: 'join',
        username: this.username,
        timestamp: Date.now()
      });
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.messageHandlers.forEach(handler => handler(message));
    };

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

    this.ws.onclose = () => {
      console.log('Disconnected from chat');
      // Attempt reconnection after 3 seconds
      setTimeout(() => this.connect(url), 3000);
    };
  }

  send(message) {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message));
    }
  }

  sendMessage(text) {
    this.send({
      type: 'message',
      username: this.username,
      text: text,
      timestamp: Date.now()
    });
  }

  onMessage(handler) {
    this.messageHandlers.push(handler);
  }

  disconnect() {
    if (this.ws) {
      this.ws.close();
    }
  }
}

// Usage
const chat = new ChatClient('Alice');
chat.connect('wss://chat.example.com');

chat.onMessage((message) => {
  if (message.type === 'message') {
    displayMessage(message.username, message.text);
  } else if (message.type === 'userJoined') {
    displayNotification(`${message.username} joined the chat`);
  }
});

document.getElementById('sendBtn').onclick = () => {
  const input = document.getElementById('messageInput');
  chat.sendMessage(input.value);
  input.value = '';
};

Server-Side Chat Implementation (Node.js)

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

const clients = new Map();

wss.on('connection', (ws) => {
  let username = null;

  ws.on('message', (data) => {
    const message = JSON.parse(data);

    if (message.type === 'join') {
      username = message.username;
      clients.set(ws, { username, joinedAt: Date.now() });

      // Broadcast user joined
      broadcast({
        type: 'userJoined',
        username: username,
        userCount: clients.size
      }, ws);
    } else if (message.type === 'message') {
      // Broadcast message to all clients
      broadcast({
        type: 'message',
        username: username,
        text: message.text,
        timestamp: message.timestamp
      });
    }
  });

  ws.on('close', () => {
    if (username) {
      clients.delete(ws);
      broadcast({
        type: 'userLeft',
        username: username,
        userCount: clients.size
      });
    }
  });
});

function broadcast(message, excludeClient = null) {
  const data = JSON.stringify(message);
  clients.forEach((clientInfo, client) => {
    if (client !== excludeClient && client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
}

This chat websocket example shows the websocket meaning in practice: persistent connections enabling instant message delivery without HTTP request overhead. For more details on WebSocket fundamentals, see What is WebSocket.

Live Dashboard and Stock Ticker

Live dashboards streaming financial data, analytics, or monitoring metrics benefit from websocket communication. This websocket application pattern pushes updates to clients immediately rather than requiring periodic polling.

class LiveDashboard {
  constructor(dashboardId) {
    this.dashboardId = dashboardId;
    this.ws = null;
    this.subscriptions = new Set();
  }

  connect() {
    this.ws = new WebSocket('wss://api.example.com/dashboard');

    this.ws.onopen = () => {
      // Authenticate and subscribe to dashboard
      this.ws.send(JSON.stringify({
        action: 'subscribe',
        dashboardId: this.dashboardId,
        metrics: Array.from(this.subscriptions)
      }));
    };

    this.ws.onmessage = (event) => {
      const update = JSON.parse(event.data);
      this.handleUpdate(update);
    };
  }

  subscribe(metricName, callback) {
    this.subscriptions.add(metricName);

    // Store callback for this metric
    if (!this.callbacks) this.callbacks = new Map();
    if (!this.callbacks.has(metricName)) {
      this.callbacks.set(metricName, []);
    }
    this.callbacks.get(metricName).push(callback);

    // If already connected, send subscription
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        action: 'subscribe',
        metric: metricName
      }));
    }
  }

  handleUpdate(update) {
    const { metric, value, timestamp } = update;

    // Update UI elements
    if (this.callbacks?.has(metric)) {
      this.callbacks.get(metric).forEach(cb => cb(value, timestamp));
    }
  }
}

// Usage: Stock ticker
const dashboard = new LiveDashboard('stocks-dashboard');

dashboard.subscribe('AAPL', (price, timestamp) => {
  document.getElementById('aapl-price').textContent = `$${price.toFixed(2)}`;
  updateChart('AAPL', price, timestamp);
});

dashboard.subscribe('GOOGL', (price, timestamp) => {
  document.getElementById('googl-price').textContent = `$${price.toFixed(2)}`;
  updateChart('GOOGL', price, timestamp);
});

dashboard.connect();

The websocket docs pattern here demonstrates selective subscription, reducing bandwidth by only receiving relevant updates. Compare this efficiency to traditional HTTP in WebSocket vs HTTP.

Multiplayer Game State Synchronization

Multiplayer games require low-latency state synchronization. This websocket example shows how to use websocket connections for real-time game updates with client-side prediction and server reconciliation.

class GameClient {
  constructor(gameId, playerId) {
    this.gameId = gameId;
    this.playerId = playerId;
    this.ws = null;
    this.sequenceNumber = 0;
    this.pendingInputs = [];
  }

  connect() {
    this.ws = new WebSocket('wss://game.example.com');

    this.ws.onopen = () => {
      this.ws.send(JSON.stringify({
        type: 'join',
        gameId: this.gameId,
        playerId: this.playerId
      }));
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleServerUpdate(message);
    };
  }

  sendInput(input) {
    const sequence = this.sequenceNumber++;

    const inputMessage = {
      type: 'input',
      sequence: sequence,
      input: input,
      timestamp: Date.now()
    };

    // Client-side prediction
    this.applyInput(input);
    this.pendingInputs.push(inputMessage);

    // Send to server
    this.ws.send(JSON.stringify(inputMessage));
  }

  handleServerUpdate(message) {
    if (message.type === 'gameState') {
      // Server reconciliation
      const { state, lastProcessedInput } = message;

      // Remove acknowledged inputs
      this.pendingInputs = this.pendingInputs.filter(
        input => input.sequence > lastProcessedInput
      );

      // Set server state
      this.setState(state);

      // Re-apply pending inputs
      this.pendingInputs.forEach(input => {
        this.applyInput(input.input);
      });

      this.render();
    } else if (message.type === 'playerJoined') {
      this.addPlayer(message.player);
    } else if (message.type === 'playerLeft') {
      this.removePlayer(message.playerId);
    }
  }

  applyInput(input) {
    // Apply input to local game state
    if (input.action === 'move') {
      this.movePlayer(this.playerId, input.direction, input.distance);
    }
  }

  movePlayer(playerId, direction, distance) {
    // Update player position based on direction and distance
    const player = this.players.get(playerId);
    if (player) {
      player.x += direction.x * distance;
      player.y += direction.y * distance;
    }
  }

  setState(state) {
    this.players = new Map(Object.entries(state.players));
    this.gameObjects = state.gameObjects;
  }

  render() {
    // Render game state to canvas
  }
}

// Usage
const game = new GameClient('room-123', 'player-456');
game.connect();

// Handle keyboard input
document.addEventListener('keydown', (e) => {
  if (e.key === 'ArrowUp') {
    game.sendInput({ action: 'move', direction: { x: 0, y: -1 }, distance: 5 });
  }
});

This websocket app pattern demonstrates client-side prediction with server reconciliation, essential for responsive gameplay. For JavaScript implementation details, check JavaScript WebSocket Guide.

Real-Time Notifications System

Push notifications keep users informed without constant polling. This websocket application delivers notifications instantly across web and mobile platforms.

class NotificationClient {
  constructor(userId, authToken) {
    this.userId = userId;
    this.authToken = authToken;
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
  }

  connect() {
    this.ws = new WebSocket('wss://notifications.example.com');

    this.ws.onopen = () => {
      console.log('Notification service connected');
      this.reconnectAttempts = 0;

      // Authenticate
      this.ws.send(JSON.stringify({
        type: 'auth',
        userId: this.userId,
        token: this.authToken
      }));
    };

    this.ws.onmessage = (event) => {
      const notification = JSON.parse(event.data);
      this.handleNotification(notification);
    };

    this.ws.onclose = () => {
      console.log('Notification service disconnected');
      this.attemptReconnect();
    };

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

  handleNotification(notification) {
    const { type, title, message, data, priority } = notification;

    // Show browser notification
    if ('Notification' in window && Notification.permission === 'granted') {
      new Notification(title, {
        body: message,
        icon: data.icon,
        tag: notification.id,
        requireInteraction: priority === 'high'
      });
    }

    // Update UI notification center
    this.addToNotificationCenter(notification);

    // Play sound for high priority
    if (priority === 'high') {
      this.playNotificationSound();
    }

    // Acknowledge receipt
    this.ws.send(JSON.stringify({
      type: 'ack',
      notificationId: notification.id
    }));
  }

  subscribe(channel) {
    this.ws.send(JSON.stringify({
      type: 'subscribe',
      channel: channel
    }));
  }

  unsubscribe(channel) {
    this.ws.send(JSON.stringify({
      type: 'unsubscribe',
      channel: channel
    }));
  }

  attemptReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(() => this.connect(), delay);
    }
  }

  addToNotificationCenter(notification) {
    // Add to UI notification list
    const notificationList = document.getElementById('notifications');
    const item = document.createElement('div');
    item.className = 'notification-item';
    item.innerHTML = `
      <strong>${notification.title}</strong>
      <p>${notification.message}</p>
      <small>${new Date(notification.timestamp).toLocaleString()}</small>
    `;
    notificationList.prepend(item);
  }

  playNotificationSound() {
    const audio = new Audio('/sounds/notification.mp3');
    audio.play().catch(e => console.log('Could not play sound:', e));
  }
}

// Usage
const notifications = new NotificationClient('user-123', 'auth-token-xyz');
notifications.connect();

// Subscribe to specific notification channels
notifications.subscribe('orders');
notifications.subscribe('messages');
notifications.subscribe('system-alerts');

Collaborative Editing

Collaborative editing tools like Google Docs use websocket communication for real-time synchronization. This websocket example demonstrates operational transformation (OT) principles for conflict resolution.

class CollaborativeEditor {
  constructor(documentId, userId) {
    this.documentId = documentId;
    this.userId = userId;
    this.ws = null;
    this.localVersion = 0;
    this.serverVersion = 0;
    this.pendingOperations = [];
  }

  connect() {
    this.ws = new WebSocket('wss://editor.example.com');

    this.ws.onopen = () => {
      this.ws.send(JSON.stringify({
        type: 'join',
        documentId: this.documentId,
        userId: this.userId
      }));
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleMessage(message);
    };
  }

  handleMessage(message) {
    switch (message.type) {
      case 'init':
        // Initialize document state
        this.setContent(message.content);
        this.serverVersion = message.version;
        this.localVersion = message.version;
        break;

      case 'operation':
        // Apply remote operation
        this.applyRemoteOperation(message.operation);
        break;

      case 'cursor':
        // Update remote cursor position
        this.updateRemoteCursor(message.userId, message.position);
        break;

      case 'user-joined':
        this.showUserJoined(message.user);
        break;

      case 'user-left':
        this.showUserLeft(message.userId);
        break;
    }
  }

  sendOperation(operation) {
    const op = {
      type: 'operation',
      documentId: this.documentId,
      userId: this.userId,
      operation: operation,
      baseVersion: this.serverVersion
    };

    this.pendingOperations.push(op);
    this.ws.send(JSON.stringify(op));
  }

  applyRemoteOperation(operation) {
    // Transform pending operations against received operation
    this.pendingOperations = this.pendingOperations.map(pending => {
      return this.transform(pending.operation, operation);
    });

    // Apply operation to document
    this.applyOperation(operation);
    this.serverVersion++;
  }

  transform(op1, op2) {
    // Operational Transformation logic
    // This is simplified; real OT is more complex
    if (op1.position < op2.position) {
      return op1;
    } else if (op1.type === 'insert' && op2.type === 'insert') {
      return { ...op1, position: op1.position + op2.text.length };
    } else if (op1.type === 'delete' && op2.type === 'insert') {
      return { ...op1, position: op1.position + op2.text.length };
    }
    return op1;
  }

  applyOperation(operation) {
    const editor = document.getElementById('editor');
    const content = editor.value;

    if (operation.type === 'insert') {
      const newContent = content.slice(0, operation.position) +
                        operation.text +
                        content.slice(operation.position);
      editor.value = newContent;
    } else if (operation.type === 'delete') {
      const newContent = content.slice(0, operation.position) +
                        content.slice(operation.position + operation.length);
      editor.value = newContent;
    }
  }

  onTextInsert(position, text) {
    this.sendOperation({
      type: 'insert',
      position: position,
      text: text
    });
  }

  onTextDelete(position, length) {
    this.sendOperation({
      type: 'delete',
      position: position,
      length: length
    });
  }

  setContent(content) {
    document.getElementById('editor').value = content;
  }

  updateRemoteCursor(userId, position) {
    // Display remote user cursor in editor
  }

  showUserJoined(user) {
    console.log(`${user.name} joined the document`);
  }

  showUserLeft(userId) {
    console.log(`User ${userId} left the document`);
  }
}

// Usage
const editor = new CollaborativeEditor('doc-789', 'user-123');
editor.connect();

// Track local edits
let lastContent = '';
document.getElementById('editor').addEventListener('input', (e) => {
  const newContent = e.target.value;
  // Calculate diff and send operations
  // Simplified: you'd need proper diff algorithm
  if (newContent.length > lastContent.length) {
    const position = e.target.selectionStart - 1;
    const text = newContent[position];
    editor.onTextInsert(position, text);
  }
  lastContent = newContent;
});

Advanced collaborative editing often uses CRDT (Conflict-free Replicated Data Types) as an alternative to OT, providing better eventual consistency guarantees for distributed systems.

IoT Sensor Monitoring

IoT devices streaming sensor data benefit from websocket connections. This websocket example shows efficient handling of high-frequency sensor updates.

class IoTMonitor {
  constructor() {
    this.ws = null;
    this.sensors = new Map();
    this.dataBuffer = [];
    this.bufferFlushInterval = 1000; // Flush every second
  }

  connect() {
    this.ws = new WebSocket('wss://iot.example.com/sensors');

    this.ws.onopen = () => {
      console.log('Connected to IoT monitoring');
      this.startBufferFlush();
    };

    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      this.processSensorData(data);
    };
  }

  processSensorData(data) {
    const { sensorId, type, value, timestamp } = data;

    // Update sensor state
    if (!this.sensors.has(sensorId)) {
      this.sensors.set(sensorId, {
        id: sensorId,
        type: type,
        readings: []
      });
    }

    const sensor = this.sensors.get(sensorId);
    sensor.readings.push({ value, timestamp });

    // Keep only last 100 readings
    if (sensor.readings.length > 100) {
      sensor.readings.shift();
    }

    // Buffer for batch processing
    this.dataBuffer.push(data);

    // Check thresholds for alerts
    this.checkThresholds(sensorId, value);

    // Update real-time display
    this.updateDisplay(sensorId, value);
  }

  checkThresholds(sensorId, value) {
    // Example: temperature sensor threshold
    if (sensorId.startsWith('temp-') && value > 80) {
      this.sendAlert({
        severity: 'warning',
        sensor: sensorId,
        message: `Temperature ${value}°F exceeds threshold`,
        timestamp: Date.now()
      });
    }
  }

  sendAlert(alert) {
    // Send alert back to server
    this.ws.send(JSON.stringify({
      type: 'alert',
      alert: alert
    }));
  }

  startBufferFlush() {
    setInterval(() => {
      if (this.dataBuffer.length > 0) {
        // Process buffered data in batch
        this.processBatch(this.dataBuffer);
        this.dataBuffer = [];
      }
    }, this.bufferFlushInterval);
  }

  processBatch(data) {
    // Aggregate statistics, store to database, etc.
    console.log(`Processing batch of ${data.length} sensor readings`);
  }

  updateDisplay(sensorId, value) {
    const element = document.getElementById(`sensor-${sensorId}`);
    if (element) {
      element.textContent = value.toFixed(2);
    }
  }

  subscribeTo(sensorIds) {
    this.ws.send(JSON.stringify({
      type: 'subscribe',
      sensors: sensorIds
    }));
  }
}

// Usage
const iotMonitor = new IoTMonitor();
iotMonitor.connect();

// Subscribe to specific sensors
iotMonitor.subscribeTo([
  'temp-001',
  'temp-002',
  'humidity-001',
  'pressure-001'
]);

For server-side implementation patterns, see Node.js WebSocket Guide.

When NOT to Use WebSocket

While WebSocket excels at real-time communication, it’s not always the right choice. Avoid websocket application development when:

Request-Response Patterns: Simple REST API calls where HTTP is more appropriate. WebSocket adds unnecessary complexity for one-time data fetches.

Caching Requirements: HTTP leverages browser caching, CDNs, and proxy caching effectively. WebSocket bypasses these mechanisms.

SEO-Critical Content: Search engines crawl HTTP endpoints but cannot index WebSocket data streams. Use server-side rendering with HTTP for public content.

Stateless Services: WebSocket maintains persistent connections requiring server memory. For stateless microservices, HTTP is more scalable.

Infrequent Updates: If updates occur less than once per minute, HTTP polling or Server-Sent Events (SSE) may be simpler and more efficient.

Binary File Transfers: While WebSocket supports binary data, HTTP with proper content-type headers and streaming is better suited for large file downloads.

Third-Party API Integration: Most external APIs use REST/HTTP. WebSocket requires both client and server to support the protocol.

The websocket meaning implies bidirectional communication, but many applications only need unidirectional server-to-client updates (use SSE) or occasional client-to-server requests (use HTTP).

Frequently Asked Questions

What is the best websocket example for beginners?

The chat application is the best websocket example for beginners. It demonstrates core concepts: establishing connections, sending/receiving messages, and handling connection lifecycle events. Start with a simple echo server, then expand to multi-user chat with broadcasting. This websocket app pattern teaches essential skills applicable to more complex use cases.

How do I handle reconnection in a websocket application?

Implement exponential backoff reconnection logic. When the WebSocket closes, wait before reconnecting, increasing the delay with each attempt (1s, 2s, 4s, 8s). Limit maximum attempts to prevent infinite loops. Include connection state management to queue messages during disconnection and resend after reconnection. Most production websocket docs recommend adding heartbeat/ping mechanisms to detect dead connections proactively.

Can I use websocket for streaming video or audio?

While technically possible, WebSocket is not optimal for media streaming. Use WebRTC for real-time video/audio communication, which provides better performance, codec support, and adaptive bitrate streaming. WebSocket works well for signaling in WebRTC applications but not for the media streams themselves. For recorded media playback, HTTP streaming protocols (HLS, DASH) are more appropriate.

What’s the difference between WebSocket and Socket.IO?

WebSocket is a protocol providing low-level bidirectional communication. Socket.IO is a library built on WebSocket (with fallbacks) that adds features like automatic reconnection, room support, event-based messaging, and broad browser compatibility. For simple websocket communication, use native WebSocket APIs. For complex applications requiring these additional features, Socket.IO simplifies development. Both serve different needs in websocket application architecture.