Sockeye/README.md

183 lines
4.8 KiB
Markdown

# Sockeye
An easy-to-use, fast, and robust C++ epoll socket library.
## API Reference
### sockeye::Socket
Main server class for handling TCP connections.
#### Constructor
```cpp
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
```cpp
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.
```cpp
#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.
```cpp
#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.
```cpp
#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;
}
```