cppnet
C++ network utilities for asynchronous servers.
Loading...
Searching...
No Matches
Cpp Network Utils (cppnet)

Tests Codacy Badge Codacy Badge

A header-only library for building asynchronous network services.

Features

  • Header-only - No compilation required, just include and go
  • TCP and UDP support - Both protocols with the same consistent API

Requirements

  • C++20 compiler (GCC 10+, Clang 13+, MSVC 2022+)
  • CMake 3.28+
  • Ninja (recommended build system)
  • Linux (other platforms may work but are untested)

Installation

Using CPM (Recommended)

Add cppnet to your CMake project using CPM:

include(cmake/CPM.cmake)
CPMAddPackage("gh:kcexn/cppnet@0.9.0")
target_link_libraries(your_target PRIVATE cppnet)

Using FetchContent

include(FetchContent)
FetchContent_Declare(
cppnet
GIT_REPOSITORY https://github.com/kcexn/cppnet.git
GIT_TAG v0.9.0
)
FetchContent_MakeAvailable(cppnet)
target_link_libraries(your_target PRIVATE cppnet)

Manual Installation

git clone https://github.com/kcexn/cppnet.git
cd cppnet
cmake --preset release
sudo cmake --install build/release

Example Applications

Some simple examples of applications built with cppnet:

Quick Start

TCP Echo Server

#include <net/cppnet.hpp>
#include <arpa/inet.h>
using namespace net::service;
// Define your service by inheriting from async_tcp_service
struct echo_service : public async_tcp_service<echo_service> {
// Constructor passes address to base class
template <typename T>
explicit echo_service(socket_address<T> address) : Base(address) {}
// Optional: configure socket options
auto initialize(const socket_handle &socket) -> std::error_code {
// Set socket options here if needed
return {};
}
// Optional: handle graceful shutdown
auto stop() -> void {
// Cleanup code here
}
// Handle incoming data - MUST call submit_recv() to continue
auto service(async_context &ctx, const socket_dialog &socket,
std::shared_ptr<read_context> rctx,
std::span<const std::byte> buf) -> void {
using namespace io::socket;
using namespace stdexec;
// Echo the data back
sender auto echo_sender =
io::sendmsg(socket, socket_message{.buffers = buf}, 0) |
then([&, socket, rctx](auto &&) {
submit_recv(ctx, socket, std::move(rctx)); // Continue reading
}) |
upon_error([](auto &&) {});
ctx.scope.spawn(std::move(echo_sender));
}
};
int main() {
// Create IPv4 address on port 8080
auto addr = io::socket::socket_address<sockaddr_in>();
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = INADDR_ANY;
addr->sin_port = htons(8080);
// Create and start the service in its own thread
ctx.start(addr);
// Wait for termination (service runs until SIGTERM/SIGINT)
ctx.state.wait(async_context::STARTED);
return 0;
}
A ServiceLike Async TCP Service.
Definition async_tcp_service.hpp:73
A threaded asynchronous service.
Definition context_thread.hpp:57
This file exports the public cppnet interface.
This namespace is for network services.
Definition async_context.hpp:31
An asynchronous execution context.
Definition async_context.hpp:34

UDP Echo Server

#include <net/cppnet.hpp>
#include <arpa/inet.h>
using namespace net::service;
struct udp_echo_service : public async_udp_service<udp_echo_service> {
template <typename T>
explicit udp_echo_service(socket_address<T> address) : Base(address) {}
auto service(async_context &ctx, const socket_dialog &socket,
std::shared_ptr<read_context> rctx,
std::span<const std::byte> buf) -> void {
using namespace io::socket;
using namespace stdexec;
// Echo back to sender (address is in rctx->msg.address)
sender auto echo_sender =
io::sendmsg(socket, rctx->msg, 0) |
then([&, socket, rctx](auto &&) {
submit_recv(ctx, socket, std::move(rctx));
}) |
upon_error([](auto &&) {});
ctx.scope.spawn(std::move(echo_sender));
}
};
int main() {
auto addr = io::socket::socket_address<sockaddr_in>();
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = INADDR_ANY;
addr->sin_port = htons(8080);
ctx.start(addr);
// Wait for termination
ctx.state.wait(async_context::STARTED);
return 0;
}
A ServiceLike Async UDP Service.
Definition async_udp_service.hpp:66

Client Factories

class client_factory {
public:
struct client_t {
async_context *ctx = nullptr;
// Relevant client methods can be implemented here.
};
auto make_client() -> client_t
{
if (ctx_.state == async_context::PENDING)
ctx_.start();
return {.ctx = std::addressof(ctx_)};
}
private:
};
basic_context_thread< detail::null_service > context_thread
Default context thread is a null service thread.
Definition context_thread.hpp:101

Building from Source

# Clone the repository
git clone https://github.com/kcexn/cloudbus-net.git
cd cloudbus-net
# Debug build (with tests and coverage)
cmake --preset debug
cmake --build --preset debug
# Release build (optimized)
cmake --preset release
cmake --build --preset release
# Run tests
ctest --preset debug --output-on-failure

Documentation

Generate API documentation with Doxygen:

cmake --preset debug -DCPPNET_BUILD_DOCS=ON
cmake --build --preset debug --target doxygen

Documentation will be in build/debug/docs/html/index.html.

Architecture

The library uses the CRTP (Curiously Recurring Template Pattern) for services:

  • **async_context** - Execution context with async_scope, I/O multiplexer, signal handling, and event loop timers
  • **context_thread<Service>** - Runs a service in a dedicated thread (default null_service is useful for network clients)
  • **async_tcp_service<Handler>** - TCP server base class with accept/read loop
  • **async_udp_service<Handler>** - UDP server base class with read loop
  • **timers<InterruptSource>** - Event-loop timers for scheduling callbacks

Your service inherits from the appropriate template and implements:

  • service() to handle received data (required - must call submit_recv() to continue)
  • initialize() to configure the socket (optional)
  • stop() for graceful shutdown (optional, TCP only)

Signal Handling

Services support two signals:

  • terminate (0) - Graceful shutdown
  • user1 (1) - Custom application signal

Send signals via async_context::signal(int signum).

License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.

Contributing

Contributions are welcome! Please ensure:

  • Code follows C++20 best practices
  • All tests pass (ctest --preset debug)
  • New features include tests and documentation
  • Code coverage is maintained

Dependencies

All dependencies are automatically fetched via CPM: