DEV Community

Jithin Prem
Jithin Prem

Posted on

Building a Real-Time Chat App with Python

Building a Real-Time Chat App with Python

Building a real-time chat application is a complex task that requires a deep understanding of web development, networking, and asynchronous programming. In this article, we will explore how to build a real-time chat app using Python, leveraging the power of WebSockets and SignalR-like hubs.

Introduction to Real-Time Communication

Real-time communication is a crucial aspect of modern web development, enabling applications to push updates to clients instantly. WebSockets, a bi-directional communication protocol, allows for efficient and low-latency communication between clients and servers. In the .NET ecosystem, SignalR is a popular library for building real-time web applications using WebSockets.

Setting up a SignalR-like Hub

To build a real-time chat app in Python, we need a SignalR-like hub that can handle WebSocket connections and broadcast messages to clients. We can use the flask-socketio library, which provides a similar functionality to SignalR. Here's an example of how to set up a basic hub:

from flask import Flask
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config["SECRET_KEY"] = "secret!"
socketio = SocketIO(app)

@socketio.on("connect")
def connect():
    emit("message", "Client connected")

@socketio.on("disconnect")
def disconnect():
    print("Client disconnected")

@socketio.on("message")
def handle_message(message):
    emit("message", message, broadcast=True)

if __name__ == "__main__":
    socketio.run(app)
Enter fullscreen mode Exit fullscreen mode

Authentication with JWT

To authenticate clients, we can use JSON Web Tokens (JWT). JWT is a compact, URL-safe means of representing claims to be transferred between two parties. We can use the pyjwt library to generate and verify JWT tokens. Here's an example of how to authenticate clients using JWT:

import jwt
from flask import request

def authenticate(token):
    try:
        payload = jwt.decode(token, "secret_key", algorithms=["HS256"])
        return payload["username"]
    except jwt.ExpiredSignatureError:
        return None

@socketio.on("connect")
def connect():
    token = request.args.get("token")
    username = authenticate(token)
    if username:
        emit("message", f"Welcome, {username}!")
    else:
        emit("message", "Invalid token")
Enter fullscreen mode Exit fullscreen mode

Handling Disconnects and Groups

To handle client disconnects and groups, we need to keep track of connected clients and their respective groups. We can use a dictionary to store client information and group membership. Here's an example of how to handle disconnects and groups:

clients = {}
groups = {}

@socketio.on("connect")
def connect():
    client_id = request.sid
    clients[client_id] = {"username": "anonymous"}
    emit("message", "Client connected")

@socketio.on("join_group")
def join_group(group_name):
    client_id = request.sid
    if client_id in clients:
        clients[client_id]["group"] = group_name
        if group_name not in groups:
            groups[group_name] = []
        groups[group_name].append(client_id)
        emit("message", f"Joined group {group_name}")

@socketio.on("leave_group")
def leave_group(group_name):
    client_id = request.sid
    if client_id in clients and group_name in groups:
        groups[group_name].remove(client_id)
        del clients[client_id]["group"]
        emit("message", f"Left group {group_name}")

@socketio.on("disconnect")
def disconnect():
    client_id = request.sid
    if client_id in clients:
        del clients[client_id]
        for group in groups.values():
            if client_id in group:
                group.remove(client_id)
        emit("message", "Client disconnected")
Enter fullscreen mode Exit fullscreen mode

Deploying to Azure

To deploy our real-time chat app to Azure, we need to set up a WebSocket-enabled Azure App Service. We can use the azure-webapp library to deploy our app to Azure. Here's an example of how to deploy our app:

from azure.common.credentials import ServicePrincipalCredentials
from azure.mgmt.web import WebSiteManagementClient

credentials = ServicePrincipalCredentials(
    client_id="client_id",
    secret="client_secret",
    tenant="tenant_id"
)

web_client = WebSiteManagementClient(credentials, "subscription_id")

web_client.web_apps.create_or_update(
    "resource_group",
    "app_service_plan",
    "web_app",
    {
        "location": "location",
        "properties": {
            "serverFarmId": "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Web/serverfarms/app_service_plan"
        }
    }
)
Enter fullscreen mode Exit fullscreen mode

Here is a simple representation of how the application will be structured:

+---------------+
|  Client   |
+---------------+
           |
           |
           v
+---------------+
|  WebSocket  |
+---------------+
           |
           |
           v
+---------------+
|  Server   |
+---------------+
           |
           |
           v
+---------------+
|  Database  |
+---------------+

And here is a more detailed representation of how the data will flow:

  +---------------+      +---------------+      +---------------+
  |  Client   | ---> |  WebSocket  | ---> |  Server   |
  +---------------+      +---------------+      +---------------+
           |                         |                         |
           |                         |                         |
           v                         v                         v
  +---------------+      +---------------+      +---------------+
  |  JWT Token  |      |  Authentication|      |  Data Storage |
  +---------------+      +---------------+      +---------------+

Example Use Case: Chat Room

Here's an example use case for our real-time chat app: a chat room where users can join and leave groups, send messages, and receive updates in real-time.

@socketio.on("send_message")
def send_message(message):
    client_id = request.sid
    group_name = clients[client_id]["group"]
    if group_name:
        for client in groups[group_name]:
            emit("message", message, room=client)
Enter fullscreen mode Exit fullscreen mode

In conclusion, building a real-time chat app with Python requires a deep understanding of WebSockets, SignalR-like hubs, authentication, and deployment. By leveraging the power of flask-socketio and pyjwt, we can build a scalable and secure real-time chat app that can handle thousands of concurrent connections. With the help of Azure, we can deploy our app to a cloud-based infrastructure that can scale to meet the needs of our users. Whether you're building a chat room, a live update feed, or a collaborative editing tool, the principles outlined in this article will provide a solid foundation for your real-time web application.

Top comments (0)