A high-performance, cross-platform TCP server library written in C++ with event-driven I/O. This library provides a clean, easy-to-use interface for building scalable network applications while leveraging the most efficient I/O multiplexing mechanism available on each platform.
- Cross-platform: Automatically uses the best I/O multiplexing mechanism for your platform
- Linux: epoll
- macOS/BSD: kqueue
- Event-driven architecture: Non-blocking I/O with efficient event handling
- Modern C++: Uses C++17 features and smart pointers for memory safety
- Easy to use: Simple interface for handling connections and data
- Header-only design: Easy integration into existing projects
- CMake support: Ready-to-use build system
- Linux (using epoll)
- macOS (using kqueue)
- FreeBSD (using kqueue)
- NetBSD (using kqueue)
- OpenBSD (using kqueue)
- DragonFly BSD (using kqueue)
- C++17 compatible compiler
- CMake 3.10 or higher
- POSIX-compliant operating system
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build the library
make
# Install (optional)
sudo make install
First, implement the ConnectionHandler
interface to handle incoming connections and data:
#include "tcpserver/connection_handler.hpp"
#include "tcpserver/connection.hpp"
#include <iostream>
class MyHandler : public tcpserver::ConnectionHandler {
public:
void onConnection(std::shared_ptr<tcpserver::Connection> connection) override {
std::cout << "New connection from " << connection->getClientAddress()
<< ":" << connection->getClientPort() << std::endl;
}
void onData(std::shared_ptr<tcpserver::Connection> connection, const std::string& data) override {
std::cout << "Received data: " << data << std::endl;
// Echo the data back to the client
connection->send("Echo: " + data);
}
void onDisconnect(std::shared_ptr<tcpserver::Connection> connection) override {
std::cout << "Connection closed from " << connection->getClientAddress()
<< ":" << connection->getClientPort() << std::endl;
}
};
#include "tcpserver/tcp_server.hpp"
#include <memory>
int main() {
// Create handler
auto handler = std::make_shared<MyHandler>();
// Create server on port 8080
tcpserver::TcpServer server(8080, handler);
// Start the server (blocking call)
server.start();
return 0;
}
Here's a complete echo server example:
#include "tcpserver/tcp_server.hpp"
#include "tcpserver/connection_handler.hpp"
#include <iostream>
#include <memory>
#include <string>
class EchoHandler : public tcpserver::ConnectionHandler {
public:
void onConnection(std::shared_ptr<tcpserver::Connection> connection) override {
std::cout << "Client connected: " << connection->getClientAddress()
<< ":" << connection->getClientPort() << std::endl;
// Send welcome message
connection->send("Welcome to the echo server! Type 'quit' to disconnect.\n");
}
void onData(std::shared_ptr<tcpserver::Connection> connection, const std::string& data) override {
std::cout << "Received: " << data;
// Check for quit command
if (data == "quit\n" || data == "quit\r\n") {
connection->send("Goodbye!\n");
connection->close();
return;
}
// Echo the data back
connection->send("Echo: " + data);
}
void onDisconnect(std::shared_ptr<tcpserver::Connection> connection) override {
std::cout << "Client disconnected: " << connection->getClientAddress()
<< ":" << connection->getClientPort() << std::endl;
}
};
int main() {
try {
auto handler = std::make_shared<EchoHandler>();
tcpserver::TcpServer server(8080, handler);
std::cout << "Starting echo server on port 8080..." << std::endl;
server.start();
} catch (const std::exception& e) {
std::cerr << "Server error: " << e.what() << std::endl;
return 1;
}
return 0;
}
The main server class that manages connections and the event loop.
TcpServer(int port, std::shared_ptr<ConnectionHandler> handler)
port
: The port number to listen onhandler
: The connection handler for processing connections
void start()
: Start the server (blocking call)void stop()
: Stop the serverbool isRunning() const
: Check if the server is runningint getPort() const
: Get the port the server is listening on
Represents a TCP connection to a client.
bool send(const std::string& data)
: Send data to the clientbool send(const char* data, size_t length)
: Send data with specified lengthvoid close()
: Close the connectionbool isClosed() const
: Check if the connection is closedint getSocket() const
: Get the socket file descriptorstd::string getClientAddress() const
: Get the client's IP addressint getClientPort() const
: Get the client's port numberstd::string getReadBuffer() const
: Get the read buffer contentvoid clearReadBuffer()
: Clear the read buffer
Abstract interface for handling connection events.
void onConnection(std::shared_ptr<Connection> connection)
: Called when a new connection is establishedvoid onData(std::shared_ptr<Connection> connection, const std::string& data)
: Called when data is receivedvoid onDisconnect(std::shared_ptr<Connection> connection)
: Called when a connection is closed
The library uses a clean separation of concerns:
- TcpServer: Manages the server socket, accepts connections, and coordinates the event loop
- Connection: Represents individual client connections with read/write capabilities
- EventLoop: Abstract interface for platform-specific I/O multiplexing
- ConnectionHandler: User-defined logic for handling connection events
The event loop automatically selects the most efficient I/O mechanism:
- Linux: Uses epoll for high-performance event handling
- macOS/BSD: Uses kqueue for efficient event notification
This library is designed for high performance:
- Non-blocking I/O prevents thread blocking
- Event-driven architecture scales well with many connections
- Platform-specific optimizations (epoll/kqueue) provide maximum efficiency
- Minimal memory allocations and efficient buffer management
The library is not thread-safe. All operations should be performed from a single thread. If you need multi-threading, consider using a thread pool to handle connection processing.
The library uses exceptions for error handling. Common exceptions include:
std::runtime_error
: For socket creation, binding, or listening failures- Platform-specific errors are wrapped in descriptive error messages
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.