|
Net++
A class-based C++ encapsulation over the POSIX Sockets API
|
net++ is a class-based C++ encapsulation over POSIX sockets providing a simple, readable interface, asynchronous support, and RAII management for persistent objects like connections.
**__Current Progress__**
Connecting to a host involves two simple steps. Client-sided applications use the conn_resolver::Resolver class to get a list of valid AddressInfo results. The conn_resolver::Resolver::try_connect() method attempts to connect to a result and returns a shared pointer to the first connection.
Setting up a listening connection is similar to the process with the POSIX API. First, create a tcp::Acceptor instance with a port to listen on and the address domain the underlying socket will use to listen on. As usual, you can call tcp::Acceptor::bind() to resolve the underlying socket to the host machine, tcp::Acceptor::listen() to listen for incoming connections, and tcp::Acceptor::accept() to create dedicated sockets for incoming connections.
You can view the full documentation here.
Errors are surfaced as std::system_error whenever low-level POSIX calls set the value of errno.
Not all errors are exceptional (See Kohlhoff, 2010) – a good example would be calling connect() to attempt connections to a host iteratively through a list of query results. Hence, system calls that are executed within an iterative sequence, which also have some reasonable expectation of failure, like bind() or connect() are exempt from throwing if they fail.
Error categories like LibraryErrorCategory and GAIErrorCategory are declared in error.hpp for error spaces separate from errno. They cover library errors such as results exhaustion - like when all iterative system calls fail for a set of Query Results - or errors emitted by getaddrinfo.
It is the responsibility of the library user to handle exceptions as follows:
For convenience, the log_error(std::system_error &e) function, which logs descriptions of errors to stderr, is made available in error.hpp
TCP Echo Server
TCP Echo Client
net++ uses libevent to execute callbacks on registered file descriptors - specifically with socket reads, writes, and accepting connections. The IOContext class defined in io_context.hpp manages the lifecycle and dispatch of the event loop.
Events are automatically registered with the IOContext upon setting their handling objects as non-blocking. For example, if an instance of tcp::Connection, conn calls conn.set_nonblocking(), a buffer event monitoring the socket's internal buffers is registered with IOContext. An IOContext object is calling by calling the default constructor:
The underlying event base that serves as the foundation for IOContext is not threadsafe by default, therefore IOContext is not threadsafe. Having multiple threads polling for IO implies setting up an IOContext per thread.