This project is a multi-client TCP chat application written in Python for a Computer Networking course. It allows multiple users to connect to a central server and exchange text messages and binary files in real-time. The application is built using the built-in socket and threading modules and features a custom network protocol for message framing and file transfer.
- Group Chat: Multiple clients can connect to a central server and broadcast messages to everyone.
- File Transfer: Supports sending and receiving any type of binary file between clients, facilitated by the server.
- Custom Protocol: Uses a simple
[4-byte length header] + [1-byte type] + [payload]protocol to handle message framing and differentiation between text and files. - Threading: The server uses a thread per client for concurrent handling. The client uses a separate thread for receiving messages to keep the UI responsive.
- Basic Commands: Includes commands like
/users,/send <filepath>,/help, and/quit. - User Experience: Provides timestamps, clear sender information, prompts for saving received files with original names, and basic error handling.
- Modular Package: Code is organized into a
pychatpackage for better structure and maintainability.
python-tcp-chat/
├── .gitignore
├── LICENSE
├── README.md # This documentation
├── run_client.py # Run this for the client
├── run_server.py # Run this for the server
└── pychat/
├── __init__.py # Makes 'pychat' a package
├── network_utils.py # Low-level send/recv logic and protocol
├── server.py # ChatServer class implementation
└── client.py # ChatClient class implementation
Communication relies on sending length-prefixed messages over TCP sockets.
- Header: Every message starts with a 4-byte unsigned integer (packed using
struct.pack("!I")) indicating the total size of the following data (Type + Payload). - Type: A single byte indicating the message type (e.g.,
\x01for Text,\x02for File). - Payload: The actual content.
- Text:
username::message_text(UTF-8 encoded) - File:
username::filename::file_binary_data - Join/Leave:
usernameor status message (UTF-8 encoded)
- Text:
The network_utils.py module handles packing/unpacking these messages (send_msg, recv_msg).
- The
ChatServerbinds to a host and port and listens for incoming connections. - For each accepted connection, it spawns a dedicated
_handle_clientthread. - The
_handle_clientthread first receives aJOINmessage to register the client's username. - It then enters a loop, using
recv_msgto wait for incoming messages from that client. - Based on the message type, it either:
- Processes a command (like
/users). - Broadcasts a
TEXTorFILEmessage to all other connected clients using the_broadcastmethod.
- Processes a command (like
- It uses a
threading.Lockto safely manage the shared dictionary of connected clients. - If a client disconnects or sends
/quit, the server removes them and broadcasts aLEAVEmessage.
- The
ChatClientconnects to the server's host and port. - It sends its username in a
JOINmessage. - It starts a background thread (
_receive_messages) dedicated to receiving data from the server usingrecv_msg. - The main thread runs an
start_input_loopthat takes user input from the command line. - User input is parsed:
- Commands (
/quit,/send,/help,/users) are handled locally or sent to the server. - Regular text is sent as a
TEXTmessage usingsend_text. - Files specified with
/send <filepath>are read, packaged into aFILEmessage payload (filename::binary_data), and sent usingsend_file.
- Commands (
- The
_receive_messagesthread handles incoming messages:- Prints
TEXT,JOIN,LEAVE, andERRORmessages with timestamps and formatting. - When a
FILEmessage arrives, it extracts the filename and binary data, saves the file to thereceived_files/directory, and notifies the user.
- Prints
-
Clone the repository:
git clone https://github.com/msmrexe/python-tcp-chat.git cd python-tcp-chat -
Run the Server: Open a terminal and run:
python run_server.py # Optional: specify host/port # python run_server.py --host 127.0.0.1 --port 12345
The server will start listening for connections.
-
Run Clients: Open one or more new terminals and run the client script, providing the server's IP address (use
127.0.0.1if running on the same machine) and your desired username.# Connect client 1 python run_client.py 127.0.0.1 -u Alice # Connect client 2 in another terminal python run_client.py 127.0.0.1 -u Bob # Optional: specify port if the server uses a different one # python run_client.py 192.168.1.100 -p 12345 -u Charlie
-
Chat and Send Files:
- Type messages and press Enter to send.
- Use
/send <path/to/your/file.ext>to send a file (e.g.,/send my_document.pdfor/send images/cat.jpg). - Use
/usersto see who is online. - Use
/helpfor commands. - Use
/quitto disconnect. Received files will appear in areceived_filessub-directory where you ran the client script.
Feel free to connect or reach out if you have any questions!
- Maryam Rezaee
- GitHub: @msmrexe
- Email: ms.maryamrezaee@gmail.com
This project is licensed under the MIT License. See the LICENSE file for full details.