Sockeye
An easy-to-use, fast, and robust C++ epoll socket library.
API Reference
sockeye::Socket
Main server class for handling TCP connections.
Constructor
explicit Socket(uint16_t port = 8080, int timeout_ms = 5000)
Constructs a server instance. timeout_ms
is the duration of inactivity in milliseconds before a client connection is automatically closed.
Methods
bool start()
Initialize the server socket and event system. Returns true
on success.
void run()
Start the event loop. This is a blocking call that runs until stop()
is called.
void stop()
Stops the server and causes the run()
loop to exit.
bool send(int client_fd, const std::string& data)
Sends data to a connected client. This method handles partial sends and ensures all data is written. Returns true
on success.
void on_connection(ConnectionHandler handler)
Set a callback to be executed when a new client connects.
void on_data(DataHandler handler)
Set a callback to be executed when data is received from a client.
void on_disconnect(DisconnectHandler handler)
Set a callback to be executed when a client disconnects for any reason (including timeout).
Handler Types
using ConnectionHandler = std::function<void(int client_fd)>;
using DataHandler = std::function<void(int client_fd, const char* data, size_t len)>;
using DisconnectHandler = std::function<void(int client_fd)>;
Examples
Basic Echo Server
This example demonstrates how to echo all received data back to the client. It captures the server
object to use the integrated send
method.
#include "sockeye.hpp"
#include <iostream>
#include <string>
int main() {
sockeye::Socket server(8080);
server.on_connection([](int client_fd) {
std::cout << "Client connected: " << client_fd << std::endl;
});
// Capture server to use its send method
server.on_data([&server](int client_fd, const char* data, size_t len) {
// Echo data back to client using the server's send method
server.send(client_fd, std::string(data, len));
});
server.on_disconnect([](int client_fd) {
std::cout << "Client disconnected: " << client_fd << std::endl;
});
if (!server.start()) {
std::cerr << "Failed to start server" << std::endl;
return 1;
}
server.run();
return 0;
}
HTTP Server with Keep-Alive
This example shows a simple HTTP server that properly handles keep-alive connections. The library automatically manages client timeouts.
#include "sockeye.hpp"
#include <iostream>
#include <string>
#include <unordered_map>
#include <mutex>
int main() {
sockeye::Socket server(8080);
// Buffers for accumulating request data per client
std::unordered_map<int, std::string> request_buffers;
std::mutex buffer_mutex;
server.on_data([&](int client_fd, const char* data, size_t len) {
std::string request_chunk(data, len);
std::lock_guard<std::mutex> lock(buffer_mutex);
request_buffers[client_fd] += request_chunk;
// Check if we have a full HTTP request
if (request_buffers[client_fd].find("\r\n\r\n") != std::string::npos) {
std::string response =
"HTTP/1.1 200 OK\r\n"
"Content-Length: 13\r\n"
"Connection: keep-alive\r\n\r\n"
"Hello, World!";
server.send(client_fd, response);
// Clear buffer for this client for the next request
request_buffers[client_fd].clear();
}
});
server.on_disconnect([&](int client_fd) {
std::cout << "Client disconnected: " << client_fd << std::endl;
std::lock_guard<std::mutex> lock(buffer_mutex);
request_buffers.erase(client_fd);
});
if (!server.start()) {
std::cerr << "Failed to start server" << std::endl;
return 1;
}
std::cout << "Server listening on port 8080" << std::endl;
server.run();
return 0;
}
Graceful Shutdown
This example shows how to catch SIGINT
(Ctrl+C) and SIGTERM
signals to shut down the server gracefully.
#include "sockeye.hpp"
#include <signal.h>
#include <iostream>
sockeye::Socket* server_ptr = nullptr;
void signal_handler(int signal) {
if (server_ptr) {
std::cout << "\nCaught signal " << signal << ", stopping server..." << std::endl;
server_ptr->stop();
}
}
int main() {
sockeye::Socket server(8080);
server_ptr = &server;
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
// Set up handlers...
server.on_connection([](int fd){ /* ... */ });
if (!server.start()) {
return 1;
}
std::cout << "Server started. Press Ctrl+C to exit." << std::endl;
server.run();
std::cout << "Server stopped." << std::endl;
return 0;
}