Of course! Here is a complete, well-commented, and easy-to-understand Python 3 chat server implementation.

This solution uses Python's built-in socket and threading libraries, which means you don't need to install any external packages.
Core Concepts
- Socket Programming: This is the foundation for all network communication. A socket is like an endpoint for sending or receiving data across a computer network. We'll use
socket.socket()to create a communication object. - Threading: A single server can only handle one client at a time using a simple loop. To handle multiple clients simultaneously, we'll use a "thread" for each client. This allows the server to be listening for new connections while also managing conversations with existing clients.
- Protocol: We need a simple rule for how messages are formatted. A robust way is to prefix each message with its length. This ensures the client knows exactly how many bytes to read before a message is complete.
The Code: chat_server.py
This single file contains the entire server logic.
import socket
import threading
import sys
# --- Configuration ---
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
# A dictionary to keep track of connected clients and their nicknames
clients = {}
def handle_client(conn, addr, nickname):
"""
Handles communication with a single client.
"""
print(f"[NEW CONNECTION] {nickname} connected from {addr}")
# Send a welcome message to the new client
welcome_msg = f"Welcome to the chat, {nickname}! Type 'exit' to leave."
conn.send(welcome_msg.encode('utf-8'))
while True:
try:
# Receive messages from the client
message = conn.recv(1024).decode('utf-8')
if not message:
# If the client sends an empty message, they have disconnected
break
# Check if the client wants to exit
if message.lower() == 'exit':
break
# Broadcast the message to all other clients
broadcast(f"{nickname}: {message}", conn)
except ConnectionResetError:
# This happens if the client closes the connection abruptly
print(f"[ERROR] Connection with {nickname} was reset.")
break
# --- Cleanup when a client disconnects ---
print(f"[DISCONNECT] {nickname} disconnected.")
# Remove the client from our dictionary
if nickname in clients:
del clients[nickname]
# Notify all other clients that this user has left
broadcast(f"SERVER: {nickname} has left the chat.", conn)
# Close the connection
conn.close()
def broadcast(message, sender_conn):
"""
Sends a message to all connected clients except the sender.
"""
for client_conn, nickname in clients.items():
if client_conn != sender_conn:
try:
client_conn.send(message.encode('utf-8'))
except:
# If sending fails, the client is likely disconnected.
# We'll let the main loop handle the cleanup.
pass
def start_server():
"""
Starts the chat server and listens for incoming connections.
"""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
print(f"[LISTENING] Server is listening on {HOST}:{PORT}")
try:
while True:
# Accept a new connection
conn, addr = server.accept()
# Prompt the new client for a nickname
conn.send("NICK".encode('utf-8'))
nickname = conn.recv(1024).decode('utf-8')
# Add the new client to our dictionary
clients[conn] = nickname
print(f"[NEW CONNECTION] {addr} connected as '{nickname}'.")
# Notify all other clients that a new user has joined
broadcast(f"SERVER: {nickname} has joined the chat.", conn)
# Start a new thread to handle the client
thread = threading.Thread(target=handle_client, args=(conn, addr, nickname))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
except KeyboardInterrupt:
print("\n[SHUTTING DOWN] Server is shutting down.")
finally:
# Close all client connections
for conn in clients:
conn.close()
# Close the server socket
server.close()
print("[SERVER STOPPED]")
if __name__ == "__main__":
start_server()
How to Run the Server
- Save the code above into a file named
chat_server.py. - Open your terminal or command prompt.
- Navigate to the directory where you saved the file.
- Run the server with the following command:
python chat_server.py
- You will see the following output, indicating the server is running and waiting for connections:
[LISTENING] Server is listening on 127.0.0.1:65432
The Client-Side Code
To test your server, you need a client. Here is a simple command-line client you can use. Save this as chat_client.py.
import socket
import threading
# --- Server Configuration ---
HOST = '127.0.0.1' # The server's IP address (localhost)
PORT = 65432 # The port used by the server
def receive_messages(client_socket):
"""Listens for messages from the server and prints them."""
while True:
try:
message = client_socket.recv(1024).decode('utf-8')
if message == "NICK":
# Handle nickname prompt
nickname = input("Enter your nickname: ")
client_socket.send(nickname.encode('utf-8'))
else:
print(message)
except:
# This means the server has closed the connection
print("Connection to the server lost.")
break
def send_messages(client_socket):
"""Gets input from the user and sends it to the server."""
while True:
message = input()
client_socket.send(message.encode('utf-8'))
if message.lower() == 'exit':
break
def start_client():
"""Connects to the server and starts send/receive threads."""
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((HOST, PORT))
print(f"Connected to the server at {HOST}:{PORT}")
except ConnectionRefusedError:
print("Could not connect to the server. Is it running?")
return
# Start a thread to listen for messages from the server
receive_thread = threading.Thread(target=receive_messages, args=(client,))
receive_thread.start()
# Start a thread to send messages from the user to the server
send_thread = threading.Thread(target=send_messages, args=(client,))
send_thread.start()
# Wait for both threads to complete
receive_thread.join()
send_thread.join()
client.close()
if __name__ == "__main__":
start_client()
How to Test the Chat Application
- Start the Server: In your first terminal, run
python chat_server.py. It will say it's listening. - Start Client 1: In a second terminal, run
python chat_client.py. It will connect and ask for a nickname (e.g., "Alice"). The server will print that Alice has joined. - Start Client 2: In a third terminal, run
python chat_client.pyagain. It will connect and ask for a nickname (e.g., "Bob"). The server will print that Bob has joined, and Alice's client will see a message that Bob has joined. - Chat!
- Type a message in Alice's terminal and press Enter. Bob will see it.
- Type a message in Bob's terminal and press Enter. Alice will see it.
- Disconnect:
- Type
exitin either client's terminal. That client will disconnect. The other client will see a message that the user has left. - Press
Ctrl+Cin the server's terminal to shut down the entire server. All connected clients will see an error and disconnect.
- Type
This example provides a solid foundation that you can expand upon with features like private messaging, user lists, or a graphical user interface (GUI).


