A robust, multithreaded client-server chat application implemented natively in C using POSIX sockets and pthreads. This project represents a complete, from-scratch implementation of a network communication protocol, capable of handling multiple concurrent connections, real-time message broadcasting, state synchronization, and persistent chat history.
This project was designed and developed as a comprehensive practical application of low-level system programming concepts. The primary purpose was to transition from theoretical understanding to practical mastery in several advanced computer science domains:
- Network Programming (Sockets): Mastering the OSI transport layer by implementing TCP/IP communication. This includes configuring IPv4 addressing (
AF_INET), port binding, listening for connections, and correctly translating byte orders (Host-to-Network and Network-to-Host usinghtonl/ntohl) to ensure cross-architecture compatibility. - Concurrency & Multithreading: Moving beyond sequential execution by utilizing POSIX threads (
pthreads). The project safely manages a main thread dedicated to accepting incoming connections while dynamically spawning detached worker threads to handle continuous I/O operations for each connected client. - Thread Synchronization: Implementing
pthread_mutex_tto resolve race conditions and enforce mutually exclusive access to shared server states (such as the active connection list and the chat history buffer). - Robust Memory Management: Applying strict memory allocation and deallocation (
malloc/free) strategies, alongside pointer arithmetic, to prevent memory leaks and segmentation faults during unpredictable client disconnections.
The repository is structured iteratively, showcasing the architectural evolution of the application across three distinct versions.
The first iteration focused on establishing the core read/write logic and data structures without the complexity of a network.
- Implementation: Designed a simple Inter-Process Communication (IPC) mechanism.
- Key Mechanisms: Established the foundational
readallandwriteallwrapper functions. These are critical in C to ensure that incomplete I/O operations (which are common in streams) are handled correctly via loops until the expected byte count is fully processed. - Limitation: Communication was strictly local and limited to basic data exchange.
The second iteration introduced the networking layer, transitioning the project to a standard Client-Server architecture over TCP/IP.
- Implementation: Integrated the
<sys/socket.h>and<arpa/inet.h>libraries. The server was configured to bind to a specific port and listen for incoming connections usingaccept(). - Protocol Definition: Implemented a structured message protocol. Instead of relying on null-terminators over a continuous stream, the application sends a 4-byte header containing the payload length, followed by the payload itself.
- Limitation: The server was single-threaded and operated with blocking I/O. It could only maintain a conversation with one client at a time; any other connection attempts were queued by the operating system until the first client disconnected.
The final iteration transformed the application into a fully functional, concurrent chat room. This required entirely re-architecting the server to handle asynchronous events and shared memory.
- Concurrency: The server's main loop now strictly accepts connections. Upon a successful
accept(), it allocates a specificclientInfostructure and spawns a detachedpthreadto execute thereceive_messagesroutine for that specific socket. - Shared State Management (Mutexes): * Client List: Implemented a dynamic data structure to track active file descriptors. When broadcasting messages, the server locks the list, iterates through it, sends the data to everyone except the sender, and unlocks it.
- Circular History Buffer: Developed a thread-safe, 100-message circular buffer. New connections immediately receive the historical context of the chat room. If the buffer fills, the oldest messages are safely shifted out.
- Dynamic Naming System: Overhauled the network protocol to transmit both the sender's name and the message payload. Added server-side command parsing (e.g.,
\name) using pointer arithmetic to update the user's identity dynamically in the shared client list. - Graceful Degradation: Implemented advanced signal and error handling. If a client exits abruptly (e.g., EOF via
Ctrl+D), or if the server crashes, the software utilizesshutdown(socket_fd, SHUT_RDWR)to unblock waiting threads, print appropriate disconnect logs, and exit cleanly without generating zombie processes.
To compile and execute this software, a POSIX-compliant environment (Linux/macOS) is required, along with the GNU Compiler Collection (GCC).
The project enforces strict compilation standards. The provided Makefile utilizes the following flags to guarantee code quality and prevent undefined behavior: -Wall -Wextra -Werror -O2 -pthread.
cd version3
makeLaunch the server executable. It will bind to the configured port and actively listen for incoming connections.
./serverIn separate terminal instances, launch the client executable. Multiple clients can be launched simultaneously to populate the chat room.
./client-
Change Display Name: By default, users are identified by their IP address. To set a custom alias, type:
\name <DesiredName> -
Disconnect: To safely terminate the session and notify the server of your departure, use the EOF signal:
Ctrl + D