Skip to content

JuhoJoona/tcp-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

TCP Server

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.

Features

  • 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

Supported Platforms

  • Linux (using epoll)
  • macOS (using kqueue)
  • FreeBSD (using kqueue)
  • NetBSD (using kqueue)
  • OpenBSD (using kqueue)
  • DragonFly BSD (using kqueue)

Requirements

  • C++17 compatible compiler
  • CMake 3.10 or higher
  • POSIX-compliant operating system

Building

# Create build directory
mkdir build && cd build

# Configure with CMake
cmake ..

# Build the library
make

# Install (optional)
sudo make install

Quick Start

1. Create a Connection Handler

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;
    }
};

2. Create and Start the Server

#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;
}

3. Complete Example

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;
}

API Reference

TcpServer

The main server class that manages connections and the event loop.

Constructor

TcpServer(int port, std::shared_ptr<ConnectionHandler> handler)
  • port: The port number to listen on
  • handler: The connection handler for processing connections

Methods

  • void start(): Start the server (blocking call)
  • void stop(): Stop the server
  • bool isRunning() const: Check if the server is running
  • int getPort() const: Get the port the server is listening on

Connection

Represents a TCP connection to a client.

Methods

  • bool send(const std::string& data): Send data to the client
  • bool send(const char* data, size_t length): Send data with specified length
  • void close(): Close the connection
  • bool isClosed() const: Check if the connection is closed
  • int getSocket() const: Get the socket file descriptor
  • std::string getClientAddress() const: Get the client's IP address
  • int getClientPort() const: Get the client's port number
  • std::string getReadBuffer() const: Get the read buffer content
  • void clearReadBuffer(): Clear the read buffer

ConnectionHandler

Abstract interface for handling connection events.

Methods

  • void onConnection(std::shared_ptr<Connection> connection): Called when a new connection is established
  • void onData(std::shared_ptr<Connection> connection, const std::string& data): Called when data is received
  • void onDisconnect(std::shared_ptr<Connection> connection): Called when a connection is closed

Architecture

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

Performance

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

Thread Safety

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.

Error Handling

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

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.

About

c++ tcp server

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published