StormByte is a comprehensive, cross-platform C++ library aimed at easing system programming, configuration management, logging, and database handling tasks. This library provides a unified API that abstracts away the complexities and inconsistencies of different platforms (Windows, Linux).
Features
- Network: Provides classes to handle portable network communication across Linux and Windows, including features such as asynchronous data handling, error management, and high-level socket APIs.
Table of Contents
- Repository
- Installation
- Modules
- Contributing
- License
Modules
Network
Overview
The Network
module of StormByte provides an intuitive API to manage networking tasks. It includes classes and methods for working with sockets and asynchronous data handling.
Features
- Socket Abstraction: Unified interface for handling TCP/IP sockets.
- Error Handling: Provides detailed error messages for network operations.
- Cross-Platform: Works seamlessly on both Linux and Windows.
- Data Transmission: Supports partial and large data transmission.
- Timeouts and Disconnections: Handles timeout scenarios and detects client/server disconnections.
Examples
Creating custom Packets
In order to ease the client/server communication, user can create their own Packets to be sent/received from client to server (and viceversa). In order to do so, users need to inherit from StormByte::Network::Packet
class and focus only on 2 methods:
- Constructors:
- A no parameter constructor to be able to empty initialize it (and use internally the
Initialize
method below)
- The second constructor can take whatever argument is needed and must initialize the internal
m_buffer
- Override protected
Initialize
function member to be able to construct the Packet via its reader
function.
This way, instead of sending raw messages over network you send/receive Packets instances, for example, a Packet which represents a std::string could be implemented as follows:
using namespace StormByte;
enum class OpCodes: unsigned short {
TestMessage = 1
};
public:
TestMessagePacket() noexcept:
Packet(static_cast<unsigned short>(OpCodes::TestMessage)) {}
TestMessagePacket(const std::string& msg) noexcept:
Packet(static_cast<unsigned short>(OpCodes::TestMessage)), m_msg(msg) {
Serializable<std::string> string_serial(m_msg);
m_buffer << string_serial.Serialize();
}
~TestMessagePacket() noexcept override = default;
const std::string& Message() const noexcept {
return m_msg;
}
private:
std::string m_msg;
Buffer::Simple buffer;
auto expected_size_buffer = reader(sizeof(std::size_t));
if (!expected_size_buffer) {
return StormByte::Unexpected<Network::PacketError>("Failed to read message size");
}
auto expected_size_serial = Serializable<std::size_t>::Deserialize(expected_size_buffer.value());
if (!expected_size_serial) {
return StormByte::Unexpected<Network::PacketError>("Failed to deserialize message size");
}
buffer << expected_size_serial.value();
auto str_buffer = reader(expected_size_serial.value());
if (!str_buffer) {
return StormByte::Unexpected<Network::PacketError>("Failed to read message");
}
buffer << str_buffer.value();
auto string_serial = Serializable<std::string>::Deserialize(buffer);
if (!string_serial) {
return StormByte::Unexpected<Network::PacketError>("Failed to deserialize message");
}
m_msg = string_serial.value();
Serializable<std::string> string_serializable(m_msg);
m_buffer << string_serializable.Serialize();
return {};
}
};
The class representing a packet. Explicitelly instantiate this class to get packets identified by the...
Definition packet.hxx:18
std::function< ExpectedBuffer(const size_t &)> PacketReaderFunction
The packet reader function type.
Definition typedefs.hxx:39
Creating a Custom Server
The Server
class can be extended to define custom behavior for handling client messages. Below is an example of a simple echo server:
#include <StormByte/network/server.hxx>
#include <StormByte/network/typedefs.hxx>
#include <StormByte/logger.hxx>
public:
EchoServer(StormByte::Network::Connection::Protocol protocol,
std::shared_ptr<StormByte::Network::Connection::Handler> handler,
std::shared_ptr<StormByte::Logger> logger) noexcept
: Server(protocol, handler, logger) {}
private:
StormByte::Network::Socket::Client& client,
}
};
int main() {
auto logger = std::make_shared<StormByte::Logger>(std::cout, StormByte::Logger::Level::Info);
auto handler = std::make_shared<StormByte::Network::Connection::Handler>();
EchoServer server(StormByte::Network::Connection::Protocol::IPv4, handler, logger);
if (!server.Start("localhost", 7070)) {
std::cerr << "Failed to start the server" << std::endl;
return 1;
}
std::cout << "Server is running..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10));
server.Stop();
std::cout << "Server stopped." << std::endl;
return 0;
}
A server class.
Definition server.hxx:16
virtual ExpectedFutureBuffer ProcessClientMessage(Socket::Client &client, FutureBuffer &message) noexcept=0
The function to process a client message and returns a reply.
std::future< Buffer::Simple > FutureBuffer
The future data type.
Definition typedefs.hxx:26
StormByte::Expected< FutureBuffer, ConnectionError > ExpectedFutureBuffer
The expected future type.
Definition typedefs.hxx:29
Creating a Custom Client
The Client class can be extended to define custom behavior for sending and receiving messages. Below is an example of a client that sends a test message to the server:
#include <StormByte/network/client.hxx>
#include <StormByte/network/typedefs.hxx>
#include <StormByte/logger.hxx>
public:
TestClient(StormByte::Network::Connection::Protocol protocol,
std::shared_ptr<StormByte::Network::Connection::Handler> handler,
std::shared_ptr<StormByte::Logger> logger) noexcept
: Client(protocol, handler, logger, nullptr) {}
void SendTestMessage(const std::string& message) {
packet << message;
auto result =
Send(packet);
if (!result) {
std::cerr << "Failed to send message: " << result.error()->what() << std::endl;
} else {
std::cout << "Message sent successfully!" << std::endl;
}
}
};
int main() {
auto logger = std::make_shared<StormByte::Logger>(std::cout, StormByte::Logger::Level::Info);
auto handler = std::make_shared<StormByte::Network::Connection::Handler>();
TestClient client(StormByte::Network::Connection::Protocol::IPv4, handler, logger);
if (!client.Connect("localhost", 7070)) {
std::cerr << "Failed to connect to the server" << std::endl;
return 1;
}
client.SendTestMessage("Hello, Server!");
client.Disconnect();
return 0;
}
The class representing a client.
Definition client.hxx:15
ExpectedPacket Send(const Packet &packet) noexcept
The function to send data to the server.