building a scalable chat application in c++ Using async io
π Project Overview
chatRoomCpp
is a simple yet powerful chat room application implemented in C++, leveraging the Boost.Asio library for asynchronous network communication and threading for managing concurrent client sessions.
What it can do:-
- Handle multiple clients simultaneously
- Enable non-blocking communication
- Efficiently manage memory and concurrency
π Key Features
- Asynchronous Communication: Non-blocking I/O with Boost.Asio.
- Multi-threading: Separate threads to manage IO and user input.
- Room Management: Centralized management of participants.
- Message Handling: Efficient encoding and decoding of messages.
ποΈ Architecture Overview
The project is structured around a few key classes:
Component | Responsibility |
---|---|
Session | Represents a client session. Manages socket communication. |
Room | Manages multiple client sessions. Broadcasts messages. |
Message | Handles encoding/decoding of chat messages. |
Server | Accepts incoming client connections. |
Client | Connects to server, handles user input/output. |
Each client connects to the server, joins a room, and can send and receive broadcasted messages asynchronously.
π₯ Some Functionalities Explained
1. Asynchronous I/O
- Boost.Asio's
async_read
andasync_write
functions enable non-blocking reads and writes over sockets. - Operations are initiated but completed later, triggering a completion handler (callback).
- Server continues handling other clients while one clientβs I/O is pending.
Example Principle:
boost::asio::async_read(socket, buffer, completion_handler);
boost::asio::async_write(socket, buffer, completion_handler);
2. TCP Sockets
- A TCP socket represents a single network connection between server and client.
- Server listens on a TCP port β accepts new sockets for incoming connections.
- Client connects to server socket.
- Communication happens by reading/writing raw bytes through the socket.
Example Principle:
boost::asio::ip::tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));
acceptor.async_accept(new_socket, accept_handler);
3. Threading Model
- Server runs the
io_context.run()
loop on the main thread. - Client spawns a dedicated thread for handling user input while I/O operations are managed asynchronously on another thread.
4. Message Management
- Each message includes a header and a body.
- Encoding/decoding ensures proper message framing during TCP communication (since TCP is a continuous stream).
π§ In-Depth: Boost.Asio Concepts Used
Boost.Asio Concept | Usage |
---|---|
async_read_until() |
Read data asynchronously until a delimiter or length is reached. |
async_write() |
Write buffers asynchronously. |
io_context.post() |
Post functions to run in the I/O context's event loop. |
Completion Handlers | Custom callbacks that execute after I/O operations complete. |
Important Practice:
- Always use
shared_from_this()
inside handlers to extend session object's lifetime during async operations.
π Low-Level Design (LLD)
LLD:-
π₯ Message Flow Explained
1. Client takes user input (e.g., a chat message).
2. Client asynchronously writes to socket.
3. Server reads data from socket asynchronously.
4. Server parses the incoming data into a Message object.
5. Server uses Room to broadcast Message to all Sessions.
6. Each Session queues the Message and asynchronously writes it to the respective client's socket.
π οΈ How to Build and Run
Clone the repository:
git clone https://github.com/singhdevhub-lovepreet/chatRoomCpp.git cd chatRoomCpp
Build the project:
make
Start the server:
./chatApp <port>
Start the client (in separate terminal):
./clientApp <port>
π§© Advanced Coding Practices Highlighted
Lifetime Safety with
std::enable_shared_from_this
:- Ensures that async operations keep the
Session
object alive safely.
- Ensures that async operations keep the
Efficient Message Encoding:
- First 4 bytes represent message size, followed by the actual message.
Proper Socket Management:
- Clean shutdowns of sockets when client disconnects.
Thread-Safe Queue Handling:
- Message queues are carefully managed per Session to avoid race conditions.
Scalable Server Design:
- Easy to scale further by adding multiple I/O threads or load balancing connections.
β¨ Conclusion
The chatRoomCpp
project brilliantly showcases how to design an asynchronous, multithreaded, scalable TCP server in modern C++.
If you're diving into network programming, real-time systems, or low-level system design, studying and extending this project will level up your engineering skills.
π Check out the full code here: chatRoomCpp GitHub Repository