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
- Save the Code:Save the code below into a file named `chat_room.py`.
- 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 - 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 - 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 stepsStep 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
