WebSocket Real-time Apps: Tutorial

author

By Freecoderteam

Sep 24, 2025

1

image

WebSocket Real-time Apps: Tutorial

Real-time applications have become an integral part of modern web development, enabling seamless communication between clients and servers without the need for constant polling. WebSocket is a protocol that allows for two-way, full-duplex communication between a client and a server, making it ideal for real-time applications like chat apps, live dashboards, collaborative editing tools, and more. In this tutorial, we'll explore how to build WebSocket-based real-time applications, covering the basics, implementation steps, and best practices.

Table of Contents

  1. Understanding WebSocket
  2. Setting Up a WebSocket Server
  3. Connecting Clients to the WebSocket Server
  4. Building a Simple Real-time Chat Application
  5. Best Practices for WebSocket Real-time Apps
  6. Troubleshooting Common Issues
  7. Conclusion

Understanding WebSocket

WebSocket is a protocol that provides full-duplex communication over a single TCP connection. Unlike traditional HTTP, which is request-response based, WebSocket allows both the client and server to send and receive messages independently. This makes it perfect for applications that require real-time data updates, such as chat applications, live updates, and multiplayer games.

Key Features of WebSocket:

  • Full-duplex communication: Both the client and server can send and receive data simultaneously.
  • Persistent connection: Once established, the connection remains open until explicitly closed.
  • Lightweight protocol: WebSocket uses a minimal overhead binary protocol for data transfer.
  • Cross-browser support: Most modern browsers support WebSocket, making it widely usable.

Setting Up a WebSocket Server

To build a real-time application, we need a WebSocket server that can handle client connections and manage message transmission. For this tutorial, we'll use Node.js with the ws package, a popular WebSocket library for Node.js.

Step 1: Install Node.js and Dependencies

First, ensure you have Node.js installed on your machine. Then, create a new project directory and install the ws package:

mkdir websocket-chat-app
cd websocket-chat-app
npm init -y
npm install ws

Step 2: Create the Server

Create a file named server.js and set up a basic WebSocket server:

// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });

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

// Handle new client connections
wss.on('connection', (ws) => {
  console.log('New client connected');

  // Send a welcome message to the new client
  ws.send('Welcome to the WebSocket Chat App!');

  // Handle incoming messages from the client
  ws.on('message', (message) => {
    console.log(`Received: ${message}`);
    // Broadcast the message to all connected clients
    wss.clients.forEach((client) => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });

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

Explanation:

  • wss.on('connection'): Triggered when a new client connects to the server.
  • ws.send(): Sends a message to the connected client.
  • wss.clients: An array of all connected clients. We use this to broadcast messages to everyone.
  • client.readyState === WebSocket.OPEN: Ensures the client is still connected before sending messages.

Step 3: Run the Server

Start the server using the following command:

node server.js

You should see the message WebSocket server running on ws://localhost:3000 in your terminal.


Connecting Clients to the WebSocket Server

Now that the server is set up, let's create a client-side application that connects to the WebSocket server and interacts with it.

Step 1: Create the HTML and JavaScript Files

Create an index.html file and a client.js file in the root directory of your project.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebSocket Chat App</title>
  <style>
    #messages {
      list-style: none;
      padding: 0;
      margin: 0;
    }
    #messages li {
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <h1>WebSocket Chat App</h1>
  <ul id="messages"></ul>
  <form id="form">
    <input type="text" id="input" autocomplete="off" placeholder="Type a message..." />
    <button>Send</button>
  </form>

  <script src="client.js"></script>
</body>
</html>

client.js

// client.js
const socket = new WebSocket('ws://localhost:3000');

// Display incoming messages
socket.onmessage = (event) => {
  const messages = document.getElementById('messages');
  const message = document.createElement('li');
  message.textContent = event.data;
  messages.appendChild(message);
};

// Handle form submission
const form = document.getElementById('form');
form.addEventListener('submit', (event) => {
  event.preventDefault();
  const input = document.getElementById('input');
  const message = input.value.trim();
  if (message) {
    socket.send(message);
    input.value = '';
  }
});

// Handle connection status
socket.onopen = () => {
  console.log('Connected to WebSocket server');
};

socket.onclose = () => {
  console.log('Disconnected from WebSocket server');
};

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

Explanation:

  • new WebSocket('ws://localhost:3000'): Creates a WebSocket connection to the server.
  • onmessage: Triggered when the server sends a message. We append it to the chat interface.
  • onopen: Triggered when the connection to the server is successfully established.
  • onclose: Triggered when the connection is closed.
  • onerror: Triggered if an error occurs during the connection.

Step 2: Test the Application

Run the WebSocket server (node server.js) and open index.html in your browser. You should see a simple chat interface. Type a message and press "Send." The message should appear in the chat, and if you open the application in another browser tab, you'll see the messages broadcasted in real-time.


Building a Simple Real-time Chat Application

Now that we have the basics covered, let's enhance our chat application by adding user names and better message formatting.

Step 1: Modify the Server to Include User Names

Update the server.js file to handle user names and format messages:

// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });

const users = new Set();

wss.on('connection', (ws) => {
  users.add(ws);

  ws.on('message', (message) => {
    const formattedMessage = `${ws.user.name}: ${message}`;
    console.log(`Received: ${formattedMessage}`);
    // Broadcast the message to all connected clients
    wss.clients.forEach((client) => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(formattedMessage);
      }
    });
  });

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

  // Handle user authentication (simulated)
  ws.user = {
    name: `User-${users.size + 1}`,
  };
  ws.send(`Welcome, ${ws.user.name}!`);
});

Explanation:

  • We maintain a Set of connected users.
  • Each user is assigned a unique name when they connect (User-1, User-2, etc.).
  • Messages are formatted with the user's name before being broadcasted.

Step 2: Update the Client to Display Messages with User Names

Update the client.js file to handle formatted messages:

// client.js
const socket = new WebSocket('ws://localhost:3000');

const messages = document.getElementById('messages');

socket.onmessage = (event) => {
  const message = document.createElement('li');
  message.textContent = event.data;
  messages.appendChild(message);
  messages.scrollTop = messages.scrollHeight; // Auto-scroll to the bottom
};

const form = document.getElementById('form');
form.addEventListener('submit', (event) => {
  event.preventDefault();
  const input = document.getElementById('input');
  const message = input.value.trim();
  if (message) {
    socket.send(message);
    input.value = '';
  }
});

socket.onopen = () => {
  console.log('Connected to WebSocket server');
};

socket.onclose = () => {
  console.log('Disconnected from WebSocket server');
};

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

Explanation:

  • The client now displays messages with user names as sent by the server.
  • Adding messages.scrollTop = messages.scrollHeight ensures the chat scrolls to the bottom whenever a new message arrives.

Best Practices for WebSocket Real-time Apps

Building scalable and maintainable WebSocket applications requires adherence to best practices. Here are some guidelines:

1. Use Secure WebSocket (WSS)

Always use the secure WebSocket protocol (wss://) to encrypt data and protect against man-in-the-middle attacks.

2. Implement Authentication and Authorization

  • Authenticate users before allowing them to connect.
  • Validate and sanitize all incoming data to prevent injection attacks.

3. Handle Disconnections Gracefully

  • Monitor client disconnections and clean up resources (e.g., removing users from the users set).
  • Implement reconnection logic on the client side using libraries like reconnecting-websocket.

4. Limit Message Size

WebSocket has a default message size limit. If you need to send large amounts of data, consider chunking it into smaller messages.

5. Use Compression

For large data transfers, enable compression (e.g., permessage-deflate) to reduce bandwidth usage.

6. Monitor and Scale

  • Use monitoring tools to track WebSocket connections, message rates, and errors.
  • Scale your server horizontally to handle increased load.

7. Error Handling

Implement robust error handling on both the client and server to manage unexpected disconnections or protocol errors.


Troubleshooting Common Issues

1. Connection Refused

  • Cause: The server is not running, or the port is blocked.
  • Solution: Ensure the server is running and check firewall settings.

2. Cross-Origin Issues

  • Cause: The client and server are on different domains.
  • Solution: Enable CORS on the server by setting appropriate headers or using a proxy.

3. Message Not Received

  • Cause: The client or server is not properly handling messages.
  • Solution: Check event listeners and ensure messages are being sent and received correctly.

4. Performance Bottlenecks

  • Cause: High traffic or inefficient message broadcasting.
  • Solution: Implement message rate limiting and optimize broadcasting logic.

Conclusion

WebSocket is a powerful protocol for building real-time applications. By following the steps outlined in this tutorial, you can create a robust WebSocket server and client that handles real-time communication efficiently. Remember to adhere to best practices such as using secure connections, implementing authentication, and monitoring your application.

Building real-time applications with WebSocket opens up endless possibilities, from chat apps to complex multiplayer games. With the right tools and knowledge, you can create highly interactive and engaging user experiences.

If you have any questions or feedback, feel free to leave a comment below! Happy coding! 😊


Feel free to explore more advanced topics like token-based authentication, WebSocket routing, and integrating with frameworks like Express.js for server-side logic.

Subscribe to Receive Future Updates

Stay informed about our latest updates, services, and special offers. Subscribe now to receive valuable insights and news directly to your inbox.

No spam guaranteed, So please don’t send any spam mail.