Online Chat Room Project (code) in Python

← Back to Projects

Online Chat Room in Python

About the project: This is a simple online chat room project. This project is built using Python's standard socket and threading libraries. It's designed as a single file that contains both the server and client logic, making it easy to run and test on your local machine.

The project code includes clear instructions on how to use it to set up a chat room where multiple clients can connect and send messages to each other.


How to Use and Run the Bot

  1. Save the Code:Save the code below into a file named `chat_room.py`.
  2. Start the Server: Open your first terminal window and run the following command. The server will start and wait for connections.
    
        python chat_room.py server
        
  3. Connect a Client:Open a second terminal window and run this command. You will be prompted to enter a name for the client.
    
        python chat_room.py client
        
  4. Connect More Clients: You can open more terminal windows and run the client command to have multiple people join the chat. Messages sent from one client will be broadcast to all others.

Project Level: Intermediate

You can directly copy the below snippet code with the help of green copy button, paste it and run it in any Python editor you have.

Steps: Follow these steps

Step 1: Copy below code using green 'copy' button.

Step 2: Paste the code on your chosen editor.

Step 3: Save the code with filename and .py extention.

Step 4: Run (Press F5 if using python IDLE).




# chat_room.py

import socket
import threading
import sys

# Constants for the server
HOST = '127.0.0.1'  # Standard loopback interface address (localhost)
PORT = 65432        # Port to listen on (non-privileged ports are > 1023)

class ChatServer:
    """
    The server side of the chat application. It listens for incoming connections,
    handles each client in a separate thread, and broadcasts messages to all
    connected clients.
    """
    def __init__(self):
        # A list to keep track of all connected client sockets
        self.clients = []
        # Create a socket object using IPv4 and TCP
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
    def start(self):
        """
        Starts the server, binds it to the host and port, and begins listening
        for client connections.
        """
        try:
            # Bind the socket to the address and port
            self.server_socket.bind((HOST, PORT))
            # Start listening for incoming connections
            self.server_socket.listen()
            print(f"Server started on {HOST}:{PORT}")
        except Exception as e:
            print(f"Failed to start server: {e}")
            sys.exit()

        while True:
            # Accept a new connection
            conn, addr = self.server_socket.accept()
            self.clients.append(conn)
            print(f"New connection from {addr}")
            
            # Start a new thread to handle the new client
            client_thread = threading.Thread(target=self.handle_client, args=(conn, addr))
            client_thread.daemon = True # Allow the main thread to exit gracefully
            client_thread.start()

    def handle_client(self, conn, addr):
        """
        Handles a single client connection in its own thread. It receives
        messages from the client and broadcasts them to everyone.
        """
        try:
            while True:
                # Receive data from the client (up to 1024 bytes)
                data = conn.recv(1024)
                if not data:
                    # If no data is received, the client has disconnected
                    break
                message = data.decode('utf-8')
                print(f"Received from {addr}: {message}")
                # Broadcast the message to all other clients
                self.broadcast(message, conn)
        except Exception as e:
            print(f"Client {addr} disconnected with an error: {e}")
        finally:
            self.remove_client(conn)

    def broadcast(self, message, sender_conn):
        """
        Sends a message to all clients in the chat room, except the sender.
        """
        for client in self.clients:
            if client != sender_conn:
                try:
                    client.sendall(message.encode('utf-8'))
                except Exception as e:
                    print(f"Failed to send message to a client: {e}")
                    self.remove_client(client)
    
    def remove_client(self, conn):
        """
        Removes a client from the active clients list.
        """
        if conn in self.clients:
            self.clients.remove(conn)
            conn.close()
            print("Client removed and connection closed.")


class ChatClient:
    """
    The client side of the chat application. It connects to the server,
    receives messages, and sends user input to the server.
    """
    def __init__(self, name):
        self.name = name
        # Create a socket object
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
    def start(self):
        """
        Connects to the server and starts separate threads for sending and
        receiving messages.
        """
        try:
            # Connect to the server
            self.client_socket.connect((HOST, PORT))
            print("Connected to the chat server. Start typing your message...")
            
            # Thread to receive messages from the server
            receive_thread = threading.Thread(target=self.receive_messages)
            receive_thread.daemon = True
            receive_thread.start()
            
            # Thread to send messages to the server
            send_thread = threading.Thread(target=self.send_messages)
            send_thread.daemon = True
            send_thread.start()
            
            # Keep the main thread alive so the daemon threads can run
            while receive_thread.is_alive() and send_thread.is_alive():
                time.sleep(1)

        except Exception as e:
            print(f"Failed to connect to the server: {e}")
            sys.exit()

    def receive_messages(self):
        """
        Listens for and prints messages received from the server.
        """
        while True:
            try:
                message = self.client_socket.recv(1024).decode('utf-8')
                if not message:
                    print("\nServer disconnected.")
                    break
                # Clear the input line and print the received message
                sys.stdout.write(f"\r{message}\n> ")
                sys.stdout.flush()
            except Exception as e:
                print(f"Error receiving message: {e}")
                break

    def send_messages(self):
        """
        Prompts the user for input and sends the message to the server.
        """
        while True:
            try:
                user_input = input("> ")
                if user_input.lower() == 'exit':
                    break
                # Send the message with the user's name
                full_message = f"{self.name}: {user_input}"
                self.client_socket.sendall(full_message.encode('utf-8'))
            except Exception as e:
                print(f"Error sending message: {e}")
                break
        self.client_socket.close()

if __name__ == '__main__':
    # A simple command-line interface to start the server or a client.
    if len(sys.argv) < 2:
        print("Usage: python chat_room.py [server|client]")
        sys.exit(1)
    
    mode = sys.argv[1].lower()
    if mode == 'server':
        server = ChatServer()
        server.start()
    elif mode == 'client':
        name = input("Enter your name: ")
        client = ChatClient(name)
        client.start()
    else:
        print("Invalid argument. Please use 'server' or 'client'.")

    


This simple setup is a great starting point. What do you think about adding a feature for users to choose their own nicknames?



← Back to Projects