A real-time multi-client chat system built from scratch with POSIX TCP sockets, C++ threads, and a small text-based protocol.
This project is a low-level networking exercise focused on the path between a TCP connection and a usable real-time messaging system.
The server accepts multiple clients, assigns unique usernames, routes broadcast/private messages, and protects shared client state with a mutex. Each client uses a dedicated receive thread so incoming messages can be displayed while the user is typing.
Status: Working educational prototype
Focus: C++ networking, TCP sockets, concurrency, and protocol design
Environment: Linux/Unix with POSIX socket support
- Multi-client TCP server
- Broadcast messaging
- Private messages with
/msg <username> <message> - Unique username validation
- Join/leave notifications
/helpcommandexitclient command- HH:MM timestamps
- Concurrent client handling with one server thread per connection
- Client receive thread for asynchronous incoming messages
- Mutex-protected shared client registry
- Basic handling of connection/disconnection failures
TCP
┌─────────────────────┐
│ │
┌─────▼─────┐ ┌─────▼─────┐
│ Client 1 │ │ Client 2 │
│ send/input│ │ send/input│
│ receive │ │ receive │
│ thread │ │ thread │
└─────┬─────┘ └─────┬─────┘
│ │
└──────────┬──────────┘
▼
┌─────────────────┐
│ TCP Chat │
│ Server │
├─────────────────┤
│ accept() │
│ thread/client │
│ username map │
│ broadcast │
│ private routing │
└─────────────────┘
server/src/server.cpp:
- Creates a TCP socket.
- Binds to port 9000.
- Listens for incoming connections.
- Accepts clients and creates a detached thread per client.
- Tracks sockets and usernames in a shared map.
- Broadcasts normal messages to other connected clients.
- Routes
/msgmessages to a matching username. - Announces joins and departures.
client/client.cpp:
- Connects to
127.0.0.1:9000. - Sends the chosen username.
- Starts a receive thread for server messages.
- Reads user input from the main thread.
- Sends messages over TCP.
- Shuts down the socket when
exitis entered.
The current protocol is intentionally minimal: raw text over TCP.
Initial connection:
<username>
Normal message:
hello everyone
Private message:
/msg Adarsh hello
Help:
/help
The server generates timestamped display messages such as:
[14:32] Adarsh: hello everyone
[14:33] [PRIVATE] Rahul: hello
This is not a framed or versioned wire protocol. TCP message boundaries are therefore not explicitly defined by the application.
- Linux/Unix environment
g++- C++17
- POSIX sockets
- GNU Make
- pthread support
cd server
makeIn another terminal:
cd client
makeBoth Makefiles compile with C++17, warnings enabled, and pthread support.
From the repository root:
./server/serverThe server listens on:
0.0.0.0:9000
./client/clientEnter a unique username when prompted.
Open additional terminals and run:
./client/clientUse different usernames to test broadcast and private messaging.
| Command | Purpose |
|---|---|
/msg <username> <message> |
Send a private message |
/help |
Show available server commands |
exit |
Disconnect the client |
Any other input is treated as a broadcast message.
Chat-app/
├── server/
│ ├── include/
│ │ └── server.h
│ ├── src/
│ │ └── server.cpp
│ └── Makefile
├── client/
│ ├── include/
│ │ └── client.h
│ ├── client.cpp
│ └── Makefile
└── README.md
The current implementation uses a deliberately simple threading model:
- Server: one detached
std::threadper connected client. - Shared state:
std::map<int, std::string>protected by astd::mutex. - Client: one main input thread plus one receive thread.
This keeps the implementation easy to follow while exposing the important concurrency problem: multiple client handlers access the same connection registry.
It is not intended to be an optimal high-concurrency architecture.
| Area | Current design | Consequence |
|---|---|---|
| I/O | Blocking POSIX sockets | Simple, but threads block on network operations |
| Server concurrency | Thread per client | Easy to reason about; thread count scales with connections |
| Protocol | Raw text | Simple, but no message framing/versioning |
| Client receive | Dedicated thread | Incoming messages can arrive asynchronously |
| Client registry | Mutex + map | Straightforward synchronization |
| Persistence | None | Messages disappear when the process stops |
| Authentication | None | Usernames are not identities |
| Encryption | None | Traffic is unencrypted |
This is a learning-focused networking prototype, not a production chat service.
Current limitations include:
- No authentication or authorization.
- No TLS/encryption.
- No persistent message history.
- No database.
- No file/media transfer.
- No rate limiting or abuse controls.
- No message IDs or delivery acknowledgements.
- No explicit application-level message framing.
- No protocol versioning.
- No graceful server shutdown path.
- Thread-per-client architecture limits scalability compared with event-driven I/O.
- No automated test suite or benchmark suite is currently provided.
These limitations are useful boundaries for future networking work rather than features the current implementation claims to provide.
- Define a length-prefixed or otherwise framed application protocol.
- Add structured message types and protocol versioning.
- Improve socket error handling and graceful server shutdown.
- Add connection lifecycle tests.
- Add integration tests with multiple clients.
- Add authentication and authorization.
- Add TLS.
- Add persistent message history.
- Measure concurrency and message-throughput limits.
- Evaluate
epoll/non-blocking I/O for higher connection counts.
The most important next engineering step is message framing: TCP is a byte stream, so relying on individual read() calls as complete messages is not a robust protocol boundary.
This project demonstrates hands-on work with:
- TCP/IP sockets
- POSIX networking APIs
- concurrent C++ programming
- synchronization with mutexes
- connection lifecycle management
- simple protocol design
- client/server architecture
It complements larger backend and distributed-systems projects by showing the lower-level networking layer directly.
Adarsh Kumar
C++ • Networking • Backend Systems • Systems Programming
MIT — see LICENSE.