< Previous: Getting Started | π Home | Next: Advanced Usage >
Basic Usage (Server)
The UdpListener class allows you to create a high-performance UDP receiver that automatically dispatches incoming datagrams to a background worker pool.
Starting the Server
#include "cppudpnet.hpp"
#include <iostream>
int main() {
// Construct UdpListener. Can bind to IPv4 (e.g., "0.0.0.0"), IPv6 (e.g., "::"), or hostname.
// Binding to "::" enables dual-stack support by default on supported operating systems.
cppudpnet::UdpListener server(8080, "0.0.0.0");
// Set a handler to process incoming datagrams
server.SetDataHandler([](uint64_t session_id, const cppudpnet::PeerAddress& peer,
const std::vector<uint8_t>& data) {
std::string text(data.begin(), data.end());
std::cout << "Received from " << peer.ToString() << ": " << text << std::endl;
});
try {
server.Start();
std::cout << "Server running. Press Enter to stop." << std::endl;
std::cin.get();
server.Stop();
} catch (const std::exception& e) {
std::cerr << "Failed to start server: " << e.what() << std::endl;
}
return 0;
}
Dynamic Port Discovery
If you want the operating system to dynamically assign an available port for you (e.g., to avoid port conflicts), you can bind to port 0. After starting the server, you can discover which port was assigned using GetLocalPort():
cppudpnet::UdpListener server(0, "0.0.0.0");
server.Start();
uint16_t assigned_port = server.GetLocalPort();
std::cout << "Server dynamically bound to port: " << assigned_port << std::endl;
Error Handling
cpp-udpnet splits error handling into two categories: synchronous and asynchronous.
- Synchronous Errors: Methods like
Start()are called directly by your application. If they fail (e.g., port in use, invalid IP), they will throw astd::system_errororstd::runtime_error. - Asynchronous Errors: If a failure occurs in the background polling thread, it is broadcasted over the internal PubSub broker to the
"error_events"topic as acppudpnet::ErrorEvent. Alternatively, you can useserver.SetErrorHandlerfor a direct callback.
Here is an example of subscribing to background error events via the PubSub broker:
auto err_sub = server.GetEventBroker().Subscribe<cppudpnet::ErrorEvent>("error_events");
worker.AddSubscription<cppudpnet::ErrorEvent>(err_sub, [](const cppudpnet::ErrorEvent& event) {
std::cerr << "Background error [" << event.error_code << "]: " << event.message << std::endl;
});
And here is an example of setting a direct error handler callback on the server:
server.SetErrorHandler([](int error_code, const std::string& message) {
std::cerr << "Direct callback error [" << error_code << "]: " << message << std::endl;
});
Connection State Events
Since UDP is connectionless, cpp-udpnet provides virtual peer session tracking. When a new peer address is seen for the first time, a Connected event is published. When a peerβs idle timeout expires, a Disconnected event is published.
cpppubsub::Worker worker;
auto sub = server.GetEventBroker().Subscribe<cppudpnet::ConnectionEvent>("state_events");
worker.AddSubscription<cppudpnet::ConnectionEvent>(sub, [&server](const cppudpnet::ConnectionEvent& event) {
if (event.state == cppudpnet::ConnectionState::Connected) {
std::cout << "New peer: " << event.peer.ToString() << std::endl;
} else {
std::cout << "Peer timed out: " << event.peer.ToString() << std::endl;
}
});
// Start the worker thread
worker.Start();
Logging
You can configure a global logger callback to capture internal logs from the cpp-udpnet library.
cppudpnet::SetLogger([](cppudpnet::LogSeverity severity, const std::string& className, const std::string& message) {
std::string sevStr;
switch (severity) {
case cppudpnet::LogSeverity::Debug: sevStr = "DEBUG"; break;
case cppudpnet::LogSeverity::Info: sevStr = "INFO"; break;
case cppudpnet::LogSeverity::Warn: sevStr = "WARN"; break;
case cppudpnet::LogSeverity::Error: sevStr = "ERROR"; break;
}
std::cout << "[" << sevStr << "] " << className << ": " << message << std::endl;
});
Server Configuration
UdpListener provides configuration methods to control socket-level behavior, resource bounds, and thread pooling:
Idle Timeout
Peers that have been inactive (no datagrams received) for longer than the specified duration are considered disconnected.
server.SetIdleTimeout(std::chrono::seconds(60)); // Default: 60s
Maximum Datagram Size
Controls the maximum size of the receive buffer for each recvfrom() call.
server.SetMaxDatagramSize(1500); // Default: 65507 (max UDP payload)
Socket Buffer Sizes
Configures the kernel socket receive and send buffer sizes.
server.SetRecvBufferSize(262144); // 256 KB
server.SetSendBufferSize(262144); // 256 KB
Configuration Profiles (UdpProfile)
Instead of tuning buffer sizes and payload parameters individually, you can apply pre-configured performance profiles using ApplyProfile() or inspect current parameters using GetProfile():
// Apply high-throughput profile
server.ApplyProfile(cppudpnet::UdpProfile::HighThroughput());
// Retrieve active profile structure
cppudpnet::UdpProfile profile = server.GetProfile();
std::cout << "Recv Buffer: " << profile.socket_recv_buffer_size << " bytes\n"
<< "Send Buffer: " << profile.socket_send_buffer_size << " bytes\n"
<< "Max Datagram: " << profile.max_datagram_size << " bytes" << std::endl;
Available Factory Presets:
UdpProfile::HighThroughput()β 32 MB receive & send buffers, 1200 bytes max datagram size. Optimized for high-rate datagram streaming over local networks.UdpProfile::HighLatency()β 16 MB receive & send buffers, 1400 bytes max datagram size. Optimized for high bandwidth-delay product links.UdpProfile::LowBandwidth()β 512 KB receive & send buffers, 1200 bytes max datagram size. Low memory profile for resource-constrained environments.UdpProfile::ReliableLAN()β 4 MB receive & send buffers, 1450 bytes max datagram size. Standard profile for LAN environments.
Broadcast
Enables the SO_BROADCAST socket option to allow sending and receiving broadcast datagrams.
server.SetBroadcast(true); // Default: false
Worker Pool Sizing
Controls the number of background worker threads. Since the underlying worker pool (cppasyncworker::WorkerPool) uses a fixed-size pool, this sets the exact size of the thread pool.
server.SetWorkerThreads(2); // Sets thread pool size to 2 (Default: std::thread::hardware_concurrency())
Replying to Peers
The UdpListener can send datagrams back to any peer using their address:
server.SetDataHandler([&server](uint64_t session_id, const cppudpnet::PeerAddress& peer,
const std::vector<uint8_t>& data) {
std::string text(data.begin(), data.end());
// Echo back to the sender
server.Send(peer, "Echo: " + text);
});
You can also send to an arbitrary host:port:
server.Send("192.168.1.100", 9000, "Hello there!");
| < Previous: Getting Started | π Home | Next: Advanced Usage > |