WebSocket: Building a Real-Time Chat Application

Overview

In this chapter, we will build a real-time chat application using WebSockets. This application will allow multiple users to join a chat room, send messages, and receive messages in real-time. We will use FastAPI for the server and JavaScript for the client.

Setting Up the Server

We will start by setting up the server using FastAPI. The server will handle WebSocket connections, manage chat rooms, and broadcast messages to all connected clients.

Step 1: Install Dependencies

First, we need to install FastAPI and Uvicorn. Open a terminal and run the following command:

pip install fastapi uvicorn

Step 2: Create the Project Structure

Create a new directory for your project and navigate into it. Inside this directory, create a file named main.py:

mkdir chat-app
cd chat-app
touch main.py

Step 3: Implement the WebSocket Server

Open main.py and add the following code to create a WebSocket server that handles chat messages:

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from typing import List

app = FastAPI()

class ConnectionManager:
    def __init__(self):
        self.active_connections: List[WebSocket] = []

    async def connect(self, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.append(websocket)

    def disconnect(self, websocket: WebSocket):
        self.active_connections.remove(websocket)

    async def broadcast(self, message: str):
        for connection in self.active_connections:
            await connection.send_text(message)

manager = ConnectionManager()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.broadcast(data)
    except WebSocketDisconnect:
        manager.disconnect(websocket)

In this code:

  • We create a ConnectionManager class to manage active WebSocket connections.
  • The connect method accepts a WebSocket connection and adds it to the list of active connections.
  • The disconnect method removes a WebSocket connection from the list of active connections.
  • The broadcast method sends a message to all active connections.
  • In the websocket_endpoint function, we handle incoming WebSocket connections, receive messages, and broadcast them to all connected clients.

Step 4: Run the Server

To run the server, use the following command:

uvicorn main:app --reload

This command tells Uvicorn to run the app instance defined in the main module. The --reload flag enables auto-reloading, so the server restarts whenever you make changes to the code.

Creating the Client

Next, we will create a simple client using HTML and JavaScript. The client will connect to the WebSocket server, send messages, and display received messages.

Step 5: Create the HTML File

Create a new file named index.html and add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat Application</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 0;
            padding: 20px;
            background-color: #f4f4f4;
        }
        .container {
            max-width: 800px;
            margin: auto;
            background: #fff;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        h1 {
            color: #333;
        }
        #messages {
            margin-top: 20px;
            border: 1px solid #ccc;
            padding: 10px;
            background: #f9f9f9;
            height: 200px;
            overflow-y: auto;
        }
        input[type="text"] {
            width: calc(100% - 100px);
            padding: 10px;
            margin-right: 10px;
        }
        button {
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Chat Application</h1>
        <input type="text" id="messageInput" placeholder="Type a message...">
        <button id="send">Send</button>
        <div id="messages"></div>
    </div>

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

This HTML file includes:

  • An input field to type messages.
  • A button to send messages.
  • A div to display received messages.
  • A link to an external JavaScript file app.js, which will contain our WebSocket client logic.

Step 6: Implement the WebSocket Client

Create a new file named app.js and add the following code:

const socket = new WebSocket('ws://localhost:8000/ws');

socket.addEventListener('open', (event) => {
    console.log('Connected to WebSocket server.');
    document.getElementById('messages').innerHTML += '<p>Connected to WebSocket server.</p>';
});

socket.addEventListener('message', (event) => {
    console.log('Message from server: ', event.data);
    document.getElementById('messages').innerHTML += '<p>' + event.data + '</p>';
});

socket.addEventListener('error', (event) => {
    console.error('WebSocket error: ', event);
    document.getElementById('messages').innerHTML += '<p>WebSocket error: ' + event + '</p>';
});

socket.addEventListener('close', (event) => {
    console.log('WebSocket closed: ', event);
    document.getElementById('messages').innerHTML += '<p>WebSocket closed.</p>';
});

document.getElementById('send').addEventListener('click', () => {
    const message = document.getElementById('messageInput').value;
    if (socket && socket.readyState === WebSocket.OPEN) {
        socket.send(message);
        document.getElementById('messageInput').value = '';
    }
});

In this code:

  • We create a new WebSocket connection to the server at ws://localhost:8000/ws.
  • We set up event listeners to handle connection open, message, error, and close events.
  • We handle the "Send" button click event to send messages to the server.

Testing the Chat Application

With the server running and the client set up, open index.html in your browser. Type a message in the input field and click "Send". You should see the message appear in the messages div, along with any messages sent by other connected clients.

Conclusion

In this chapter, we have built a real-time chat application using WebSockets. We set up a FastAPI server to handle WebSocket connections and implemented a simple client using HTML and JavaScript. This application allows multiple users to join a chat room, send messages, and receive messages in real-time.

In the next chapter, we will discuss debugging and monitoring WebSocket applications to ensure they run smoothly and efficiently.

Comments

Leave a Reply