Skip to content
All essays
ArchitectureFebruary 23, 202510 min

WebSockets and Real-Time Communication

Master WebSockets for real-time apps. Build chat, notifications, and live updates.

Ü
Ümit Uz
Mobile & Full Stack Developer

What are WebSockets?

Full-dupex communication channel over a single TCP connection.

WebSocket vs HTTP

HTTP:
- Request-Response
- Stateless
- One-way communication
- Overhead per request

WebSocket:
- Persistent connection
- Stateful
- Bidirectional communication
- Low latency

Client-Side WebSocket API

javascript
// Create WebSocket connection
const socket = new WebSocket('ws://localhost:8080');

// Connection opened
socket.addEventListener('open', (event) => {
  console.log('Connected to server');
  socket.send('Hello Server!');
});

// Listen for messages
socket.addEventListener('message', (event) => {
  console.log('Message from server:', event.data);
});

// Connection closed
socket.addEventListener('close', (event) => {
  console.log('Disconnected from server');
});

// Error handling
socket.addEventListener('error', (event) => {
  console.error('WebSocket error:', event);
});

React Hook

javascript
import { useEffect, useState } from 'react';

function useWebSocket(url) {
  const [socket, setSocket] = useState(null);
  const [messages, setMessages] = useState([]);
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const ws = new WebSocket(url);

    ws.onopen = () => {
      setConnected(true);
      setSocket(ws);
    };

    ws.onmessage = (event) => {
      setMessages(prev => [...prev, event.data]);
    };

    ws.onclose = () => {
      setConnected(false);
    };

    return () => {
      ws.close();
    };
  }, [url]);

  const sendMessage = (message) => {
    if (socket && connected) {
      socket.send(message);
    }
  };

  return { messages, sendMessage, connected };
}

// Usage
function Chat() {
  const { messages, sendMessage, connected } = useWebSocket('ws://localhost:8080');

  return (
    <div>
      <p>Status: {connected ? 'Connected' : 'Disconnected'}</p>
      <ul>
        {messages.map((msg, i) => <li key={i}>{msg}</li>)}
      </ul>
      <button onClick={() => sendMessage('Hello')}>Send</button>
    </div>
  );
}

Server-Side (Node.js)

javascript
import { WebSocketServer } from 'ws';

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

const clients = new Set();

wss.on('connection', (ws) => {
  console.log('New client connected');
  clients.add(ws);

  // Send welcome message
  ws.send('Welcome to the server!');

  // Handle incoming messages
  ws.on('message', (message) => {
    console.log('Received:', message.toString());

    // Broadcast to all clients
    clients.forEach(client => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });

  // Handle disconnect
  ws.on('close', () => {
    console.log('Client disconnected');
    clients.delete(ws);
  });

  // Handle errors
  ws.on('error', (error) => {
    console.error('WebSocket error:', error);
  });
});

console.log('WebSocket server running on ws://localhost:8080');

Socket.io (Simplified WebSockets)

Server

javascript
import { Server } from 'socket.io';

const io = new Server(3000);

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

  // Join room
  socket.on('join-room', (room) => {
    socket.join(room);
    socket.to(room).emit('user-joined', socket.id);
  });

  // Handle messages
  socket.on('message', (data) => {
    io.to(data.room).emit('message', {
      user: socket.id,
      text: data.text
    });
  });

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

Client

javascript
import io from 'socket.io-client';

const socket = io('http://localhost:3000');

// Join room
socket.emit('join-room', 'chat-room');

// Send message
socket.emit('message', {
  room: 'chat-room',
  text: 'Hello!'
});

// Listen for messages
socket.on('message', (data) => {
  console.log(data.user, data.text);
});

Authentication

javascript
// Server: Authenticate connection
wss.on('connection', (ws, req) => {
  const token = new URL(req.url, 'http://localhost').searchParams.get('token');

  try {
    const decoded = jwt.verify(token, SECRET);
    ws.userId = decoded.userId;
  } catch (error) {
    ws.close(4001, 'Unauthorized');
  }
});

Reconnection Strategy

javascript
class ReconnectingWebSocket {
  constructor(url) {
    this.url = url;
    this.reconnectDelay = 1000;
    this.maxReconnectDelay = 30000;
    this.connect();
  }

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

    this.ws.onopen = () => {
      console.log('Connected');
      this.reconnectDelay = 1000;  // Reset
    };

    this.ws.onclose = () => {
      console.log('Disconnected, reconnecting...');
      setTimeout(() => {
        this.connect();
      }, this.reconnectDelay);

      this.reconnectDelay = Math.min(
        this.reconnectDelay * 2,
        this.maxReconnectDelay
      );
    };
  }

  send(data) {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(data);
    }
  }
}

Use Cases

  • Chat applications: Real-time messaging
  • Live updates: Stock prices, sports scores
  • Collaboration: Google Docs-like editing
  • Gaming: Multiplayer games
  • Notifications: Push notifications

Real-time is the future!

Related essays

Next essay
Flutter Development: Cross-Platform Apps with Dart