Project Overview
This capstone project brings together everything you have learned in the C++ course to build a production-grade chat application. You will implement a multi-threaded server handling 1000+ concurrent connections, design a custom binary protocol with message framing and serialization, implement TLS/SSL encryption using OpenSSL, and create a cross-platform client with async I/O. This is the same architecture used by professional messaging platforms like Slack, Discord, and Microsoft Teams.
TCP Server
Multi-threaded server with thread pool and async I/O
Protocol Layer
Binary message format with framing and serialization
Security
TLS/SSL encryption and user authentication
Chat Client
Cross-platform CLI with real-time messaging
Learning Objectives
Technical Skills
- Master TCP/UDP socket programming with Asio
- Design efficient binary protocols with serialization
- Implement thread-safe data structures with mutexes
- Build async I/O systems with event loops
- Integrate TLS/SSL encryption with OpenSSL
Industry Skills
- Architect scalable distributed systems
- Handle thousands of concurrent connections
- Design backward-compatible protocol versions
- Implement security best practices
- Write production-quality networking code
Company Scenario
ConnectHub Technologies
You have been hired as a Senior Network Engineer at ConnectHub Technologies, a fast-growing startup building the next generation of secure enterprise messaging. The company is competing with Slack and Microsoft Teams by offering a self-hosted, highly customizable chat platform for businesses with strict security requirements (healthcare, finance, government).
"Our enterprise clients need a messaging system that can handle 10,000+ concurrent users, supports end-to-end encryption, and runs on their own infrastructure. We need you to build the core chat infrastructure from scratch. It must be fast, secure, and rock-solid reliable."
Technical Requirements from Client
- Support 1000+ concurrent connections per server
- Message latency under 50ms at P99
- Handle 10,000+ messages per second
- Efficient memory usage (<100KB per connection)
- TLS 1.3 encryption for all connections
- Secure password hashing (Argon2/bcrypt)
- Protection against replay attacks
- Rate limiting to prevent DoS
- Public and private chat rooms
- Direct messaging between users
- User presence (online/offline/away)
- Typing indicators and read receipts
- Graceful handling of disconnections
- Message delivery guarantees
- Automatic reconnection
- Cross-platform support (Windows, Linux, macOS)
Test Dataset
We provide comprehensive test data to validate your implementation across connection handling, messaging, security, and performance scenarios:
Test Data Downloads
Download the test datasets to validate your chat application. These files contain test scenarios for all major functionality.
Original Data Source
This project uses test scenarios based on the Network Traffic Dataset from Kaggle - a comprehensive dataset for network protocol analysis and chat application testing. The dataset contains real-world network patterns with connection logs, message sequences, and protocol validation data.
Test Categories
| Category | Count | Description |
|---|---|---|
connection | 50 | TCP/UDP connect, disconnect, reconnect, keepalive |
auth | 30 | Login, logout, invalid credentials, session management |
messaging | 75 | Send, receive, broadcast, private messages, Unicode |
room | 50 | Create, join, leave, list rooms, member management |
presence | 25 | Online/offline status, typing indicators, last seen |
protocol | 30 | Framing, checksums, sequence numbers, compression |
edge_case | 40 | Disconnection during send, malformed packets, timeouts |
| Metric | Tests | Description |
|---|---|---|
throughput | 30 | Messages per second at various connection counts |
latency | 25 | Round-trip time percentiles (P50, P99, P99.9) |
connection | 20 | Connection rate, max concurrent, stability |
memory | 15 | Memory per connection, leak detection |
cpu | 15 | CPU usage under various load conditions |
stress | 25 | Sustained load, spike handling, recovery |
scalability | 20 | Linear scaling, bottleneck identification |
Validates binary protocol implementation including message types (HANDSHAKE, AUTH, MESSAGE, JOIN, LEAVE, etc.), field types and sizes, required vs optional fields, validation rules, and serialization/deserialization.
Comprehensive security testing including authentication attacks (brute force, credential stuffing), encryption validation (TLS downgrade, weak ciphers), injection attacks (SQL, XSS, command), DoS protection (flood, slowloris), buffer overflow prevention, and privilege escalation tests. Each test includes CVSS score and CWE ID.
Project Requirements
Your project must include all of the following components. Structure your deliverables with clear organization, documentation, and test coverage.
Network Layer (200 points)
TCP Server Implementation:
- Multi-threaded server with configurable thread pool size
- Accept connections on configurable port (default 8080)
- Handle client disconnect gracefully (no resource leaks)
- Support at least 1000 concurrent connections
- Implement TCP keepalive mechanism for dead connection detection
Async I/O with Asio:
- Non-blocking read/write operations
- Event-driven architecture with completion handlers
- Proper error handling and connection state management
src/server/ containing ChatServer.cpp, Session.cpp,
and supporting network layer code using standalone Asio or Boost.Asio.
Protocol Design (150 points)
Binary Message Format:
- Fixed-size header (16 bytes): version, type, flags, sequence, length, checksum
- Variable-length payload with efficient serialization
- Message types: HANDSHAKE, AUTH, CHAT, PRIVATE, JOIN, LEAVE, LIST, PING, ERROR
- CRC32 checksum for data integrity
- Protocol versioning for backward compatibility
Serialization:
- Efficient binary encoding (network byte order)
- String length-prefixing for variable-length data
- Optional: message compression (zlib, LZ4)
include/chat/Protocol.hpp with message structures,
src/common/Protocol.cpp with serialization/deserialization, and
docs/protocol.md documenting the wire format.
Chat Features (200 points)
User Management:
- User registration with unique username validation
- Authentication with session tokens
- User presence tracking (online/offline/away/busy)
- Typing indicators with automatic timeout
Messaging:
- Public chat rooms (create, join, leave, list)
- Room-based message broadcasting
- Private/direct messaging between users
- Message history (in-memory, optional persistence)
- Unicode support (UTF-8 encoding)
src/server/ChatRoom.cpp with room management,
message handlers in Session.cpp, and user management functionality.
Security (100 points)
Encryption:
- TLS/SSL using OpenSSL or BoringSSL
- Support for TLS 1.2 and 1.3
- Certificate validation (optional: self-signed for development)
Authentication:
- Secure password hashing (bcrypt or Argon2)
- Session tokens with expiration
- Rate limiting to prevent brute force attacks
- Input validation and sanitization
Code Quality (100 points)
Modern C++ Practices:
- C++17 or C++20 standard features
- RAII for all resource management
- Smart pointers (no manual new/delete)
- Exception-safe code with proper error handling
Build & Documentation:
- CMake build system with proper targets
- Cross-platform support (Windows, Linux, macOS)
- Unit tests with Google Test (80% coverage)
- API documentation with Doxygen comments
Architecture
The following code examples demonstrate the expected architecture. Use these as starting points for your implementation.
// server/ChatServer.hpp
#pragma once
#include <asio.hpp>
#include <memory>
#include <unordered_map>
#include <shared_mutex>
#include "Session.hpp"
#include "ChatRoom.hpp"
namespace chat {
class ChatServer {
public:
ChatServer(asio::io_context& io_context, uint16_t port);
void start();
void stop();
// Room management
std::shared_ptr<ChatRoom> createRoom(const std::string& name);
std::shared_ptr<ChatRoom> getRoom(const std::string& name);
std::vector<std::string> listRooms() const;
// User management
void registerUser(const std::string& username, std::shared_ptr<Session> session);
void unregisterUser(const std::string& username);
std::shared_ptr<Session> getUser(const std::string& username);
// Message routing
void broadcast(const Message& msg);
void sendToUser(const std::string& username, const Message& msg);
void sendToRoom(const std::string& room, const Message& msg);
private:
void acceptConnections();
void handleAccept(std::shared_ptr<Session> session,
const asio::error_code& error);
asio::io_context& io_context_;
asio::ip::tcp::acceptor acceptor_;
mutable std::shared_mutex users_mutex_;
std::unordered_map<std::string, std::shared_ptr<Session>> users_;
mutable std::shared_mutex rooms_mutex_;
std::unordered_map<std::string, std::shared_ptr<ChatRoom>> rooms_;
bool running_ = false;
};
} // namespace chat
// server/Session.hpp
#pragma once
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <memory>
#include <queue>
#include <mutex>
#include "Protocol.hpp"
namespace chat {
class ChatServer;
class Session : public std::enable_shared_from_this<Session> {
public:
using ssl_socket = asio::ssl::stream<asio::ip::tcp::socket>;
Session(asio::io_context& io_context,
asio::ssl::context& ssl_context,
ChatServer& server);
ssl_socket::lowest_layer_type& socket() { return socket_.lowest_layer(); }
void start();
void stop();
void send(const Message& msg);
const std::string& username() const { return username_; }
void setUsername(const std::string& name) { username_ = name; }
bool isAuthenticated() const { return authenticated_; }
private:
void doHandshake();
void doRead();
void doWrite();
void processMessage(const Message& msg);
// Message handlers
void handleAuth(const Message& msg);
void handleChat(const Message& msg);
void handleJoin(const Message& msg);
void handleLeave(const Message& msg);
ssl_socket socket_;
ChatServer& server_;
std::string username_;
bool authenticated_ = false;
std::array<uint8_t, 65536> read_buffer_;
std::vector<uint8_t> message_buffer_;
std::mutex write_mutex_;
std::queue<std::vector<uint8_t>> write_queue_;
bool writing_ = false;
};
} // namespace chat
// client/ChatClient.hpp
#pragma once
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <functional>
#include <queue>
#include <thread>
#include "Protocol.hpp"
namespace chat {
class ChatClient {
public:
using MessageCallback = std::function<void(const Message&)>;
using ErrorCallback = std::function<void(const std::string&)>;
ChatClient();
~ChatClient();
// Connection
bool connect(const std::string& host, uint16_t port);
void disconnect();
bool isConnected() const { return connected_; }
// Authentication
bool authenticate(const std::string& username, const std::string& password);
// Messaging
void sendMessage(const std::string& room, const std::string& content);
void sendPrivateMessage(const std::string& recipient, const std::string& content);
// Room operations
void joinRoom(const std::string& room);
void leaveRoom(const std::string& room);
void listRooms();
// Callbacks
void onMessage(MessageCallback callback) { message_callback_ = callback; }
void onError(ErrorCallback callback) { error_callback_ = callback; }
private:
void ioThread();
void doRead();
void doWrite();
void send(const Message& msg);
asio::io_context io_context_;
asio::ssl::context ssl_context_;
std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket>> socket_;
std::thread io_thread_;
bool connected_ = false;
bool authenticated_ = false;
MessageCallback message_callback_;
ErrorCallback error_callback_;
};
} // namespace chat
// common/ThreadPool.hpp
#pragma once
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
namespace chat {
class ThreadPool {
public:
explicit ThreadPool(size_t num_threads = std::thread::hardware_concurrency());
~ThreadPool();
// Submit a task and get a future for the result
template<typename F, typename... Args>
auto submit(F&& f, Args&&... args)
-> std::future<std::invoke_result_t<F, Args...>>
{
using return_type = std::invoke_result_t<F, Args...>;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> result = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex_);
if (stop_) throw std::runtime_error("ThreadPool stopped");
tasks_.emplace([task]() { (*task)(); });
}
condition_.notify_one();
return result;
}
size_t pendingTasks() const;
size_t size() const { return workers_.size(); }
private:
std::vector<std::thread> workers_;
std::queue<std::function<void()>> tasks_;
mutable std::mutex queue_mutex_;
std::condition_variable condition_;
bool stop_ = false;
};
} // namespace chat
Protocol Design
Design a binary protocol with efficient serialization. The following shows the recommended message format and types.
struct MessageHeader {
uint8_t version; // Protocol version (1)
uint8_t type; // MessageType enum
uint16_t flags; // Encrypted, compressed, etc.
uint32_t sequence; // For ordering/acks
uint32_t payload_size; // Payload length
uint32_t checksum; // CRC32 of payload
};
enum class MessageType : uint8_t {
HANDSHAKE = 0x01,
HANDSHAKE_ACK = 0x02,
PING = 0x03,
PONG = 0x04,
AUTH_REQUEST = 0x10,
AUTH_SUCCESS = 0x12,
AUTH_FAILURE = 0x13,
CHAT_MESSAGE = 0x20,
PRIVATE_MESSAGE = 0x21,
ROOM_JOIN = 0x31,
ROOM_LEAVE = 0x32,
ERROR = 0xFF
};
docs/protocol.md. Include byte-level diagrams showing header layout,
each message type's payload format, and example encoded messages.
Submission Requirements
Submit your project as a GitHub repository with the following structure:
cpp-network-chat/
├── CMakeLists.txt
├── README.md
├── LICENSE
├── .gitignore
├── include/
│ ├── chat/
│ │ ├── Protocol.hpp
│ │ ├── Message.hpp
│ │ └── ThreadPool.hpp
│ ├── server/
│ │ ├── ChatServer.hpp
│ │ └── Session.hpp
│ └── client/
│ └── ChatClient.hpp
├── src/
│ ├── server/
│ │ ├── main.cpp
│ │ ├── ChatServer.cpp
│ │ └── Session.cpp
│ ├── client/
│ │ ├── main.cpp
│ │ └── ChatClient.cpp
│ └── common/
│ └── Protocol.cpp
├── tests/
│ ├── test_protocol.cpp
│ └── test_integration.cpp
└── docs/
├── protocol.md
└── architecture.md
Build Instructions
# Clone and build
git clone https://github.com/yourusername/cpp-network-chat.git
cd cpp-network-chat
# Configure with CMake
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
# Build
cmake --build . -j$(nproc)
# Run tests
ctest --output-on-failure
# Run server
./bin/chat_server --port 8080
# Run client
./bin/chat_client --host localhost --port 8080
Ready to Submit?
Ensure your repository is named cpp-network-chat and all tests pass.
Grading Rubric
- TCP server accepts connections (40 pts)
- Thread pool implementation (40 pts)
- Async I/O with Asio (40 pts)
- 1000+ concurrent connections (40 pts)
- Graceful disconnect handling (40 pts)
- Binary message format (30 pts)
- Serialization/deserialization (30 pts)
- Message framing (30 pts)
- Checksum validation (30 pts)
- Protocol documentation (30 pts)
- User authentication (40 pts)
- Chat rooms (create/join/leave) (40 pts)
- Room messaging & broadcast (40 pts)
- Private/direct messaging (40 pts)
- User presence & typing (40 pts)
- TLS/SSL encryption (40 pts)
- Password hashing (20 pts)
- Session management (20 pts)
- Rate limiting (20 pts)
- Modern C++17/20 (25 pts)
- RAII & smart pointers (25 pts)
- Unit tests (80% coverage) (25 pts)
- Documentation & README (25 pts)
Bonus Points (up to 100)
| Feature | Points | Description |
|---|---|---|
| UDP Support | +20 | Real-time features via UDP (typing, presence) |
| File Transfer | +20 | Send/receive files with progress |
| Message Persistence | +20 | SQLite storage for chat history |
| GUI Client | +20 | Qt or ImGui graphical interface |
| WebSocket Gateway | +20 | Browser client support |