LIBWIRE
Next-generation C++17 networking library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Public Member Functions | List of all members
libwire::tcp::socket Class Reference

Descriptor wrapper for TCP socket. More...

#include <socket.hpp>

Public Member Functions

 socket () noexcept=default
 Create new socket object. More...
 
 socket (internal_::socket &&i) noexcept
 Initialize socket from underlying raw handle. More...
 
 socket (const socket &)=delete
 
 socket (socket &&) noexcept=default
 
 ~socket ()
 Shutdown and then close socket. More...
 
void close () noexcept
 Close and destroy underlying socket. More...
 
void connect (endpoint target, std::error_code &ec) noexcept
 Initialize underlying socket and connect to remote endpoint. More...
 
bool is_open () const
 Check whether underlying socket is open. More...
 
internal_::socket::native_handle_t native_handle () const noexcept
 Get native handle/descriptor for socket. More...
 
socketoperator= (const socket &)=delete
 
socketoperator= (socket &&) noexcept=default
 
void shutdown (bool read=true, bool write=true) noexcept
 Shutdown reading/writing part of full-duplex connection (or both if read and write is true). More...
 
Socket options

Several aspects of socket behavior can be changes by setting flags.

For example: You can disable Nagle's algorithm and specify smaller retransmission timeout using following code:

socket.set_option(tcp::no_delay, true);
socket.set_option(tcp::user_timeout, 500ms);

Even more, if some platform-specific option is not provided by generic libwire interface you can add it easily because option is just a class with two static functions.

struct example_option_t {
bool get(const tcp::socket& sock) const noexcept {
return true;
}
void set(tcp::socket& sock, bool value) const noexcept {
// You can just not declare this function if option
// can't be set.
// Use sock.native_handle() here to directly
// interact with system API.
}
} example_option{};

With example above you can write:

socket.set_option(example_option, true);
socket.option(example_option); // => true
template<typename Option >
auto option (const Option &) const noexcept
 Query socket option value specified by type tag Option. More...
 
template<typename Option , typename... Args>
void set_option (const Option &, Args &&...args) noexcept
 Set socket option value specified by type tag Option to value value. More...
 
Connection Endpoints Information

Get address and port of local/remote end of connection.

Pair of endpoints uniquely identifies active connection, server can use remote_endpoint() to identify "sessions", client can use local_endpoint() for same purpose.

Return value is undefined if is_open() = false.

Example

socket.connect({1, 2, 3, 4}, 5);
socket.remote_endpoint(); // Will return 1.2.3.4:5.
socket.local_endpoint(); // Will return LOCAL-IP:RANDOM-PORT.
endpoint local_endpoint () const noexcept
 Get address and port of local end of connection. More...
 
endpoint remote_endpoint () const noexcept
 Get address and port of remote end of connection. More...
 
Blocking I/O

I/O functions in this category usually block thread until operation is completed.

template<typename Buffer = std::vector<uint8_t>>
Buffer & read (size_t bytes_count, Buffer &, std::error_code &) noexcept
 Read up to bytes_count bytes from socket into buffer passed by reference. More...
 
template<typename Buffer = std::vector<uint8_t>>
Buffer read (size_t bytes_count, std::error_code &) noexcept
 Same as overload with Buffer argument but return newly allocated buffer every time. More...
 
template<typename Buffer = std::vector<uint8_t>>
Buffer & read_until (uint8_t delimiter, Buffer &buf, std::error_code &, size_t max_size=0) noexcept
 Read from socket until until gives byte is found or max_size bytes read. More...
 
template<typename Buffer = std::vector<uint8_t>>
Buffer read_until (uint8_t delimiter, std::error_code &, size_t max_size=0) noexcept
 Same as overload with buffer argument but returns newly allocated buffer every time. More...
 
template<typename Buffer = std::vector<uint8_t>>
size_t write (const Buffer &, std::error_code &) noexcept
 Write contents of buffer to socket. More...
 

Detailed Description

Descriptor wrapper for TCP socket.

TCP (Transmission Control Protocol) is a reliable, stream-oriented, connection-oriented transport protocol. It is especially well suited for continuous transmission of data.

There is simplified graph of TCP socket states:

libwire-tcp-flow.png
Thread-safety

Definition at line 59 of file socket.hpp.

Constructor & Destructor Documentation

libwire::tcp::socket::socket ( )
defaultnoexcept

Create new socket object.

Implementation Note: Constructor itself doesn't allocates socket descriptor. It's done on connect call. This is done to allow socket to be constructed without knowing remote endpoint IP version ahead-of-time.

libwire::tcp::socket::socket ( internal_::socket &&  i)
noexcept

Initialize socket from underlying raw handle.

Used by tcp::listener for listener::accept function. Not part of the public API.

libwire::tcp::socket::socket ( const socket )
delete
libwire::tcp::socket::socket ( socket &&  )
defaultnoexcept
libwire::tcp::socket::~socket ( )

Shutdown and then close socket.

Member Function Documentation

void libwire::tcp::socket::close ( )
noexcept

Close and destroy underlying socket.

Closed socket object CAN be reused by calling connect.

May block if socket has untransmitted data even if socket is in non-blocking mode.

void libwire::tcp::socket::connect ( endpoint  target,
std::error_code &  ec 
)
noexcept

Initialize underlying socket and connect to remote endpoint.

Note
If connect called for already connected socket if active connection will be closed.
bool libwire::tcp::socket::is_open ( ) const

Check whether underlying socket is open.

Warning
Even if is_open returns true connection may be in "half-open" state. Remote side possibly already called close() and destroyed socket. In this case your next attempt to perform I/O will result in broken_pipe/connection_reset/etc error (generic for these errors is error::generic::disconnected).
endpoint libwire::tcp::socket::local_endpoint ( ) const
noexcept

Get address and port of local end of connection.

Address is a local address of interface used for connection and port is randomly picked from implementation-defined range of ephemeral ports (usually 49152-65535).

internal_::socket::native_handle_t libwire::tcp::socket::native_handle ( ) const
noexcept

Get native handle/descriptor for socket.

Returned value is undefined if is_open returns false.

socket& libwire::tcp::socket::operator= ( const socket )
delete
socket& libwire::tcp::socket::operator= ( socket &&  )
defaultnoexcept
template<typename Option >
auto libwire::tcp::socket::option ( const Option &  ) const
inlinenoexcept

Query socket option value specified by type tag Option.

Example:

socket.option(tcp::no_delay); // => false by default.
// Some options May have multiple values returned in tuple.
auto [ enabled, timeout ] = socket.option(tcp::linger);

Definition at line 160 of file socket.hpp.

template<typename Buffer >
Buffer & libwire::tcp::socket::read ( size_t  bytes_count,
Buffer &  output,
std::error_code &  ec 
)
noexcept

Read up to bytes_count bytes from socket into buffer passed by reference.

Buffer will be resized to actual count of bytes received.

Error code will be set to error code if anything went wrong, buffer will be resized to 0 elements.

Buffer type requirements:

Buffer must be container that encapsulates dynamic array, so it must have data, size and resize member functions with behavior as in std::vector.

Definition at line 380 of file socket.hpp.

template<typename Buffer >
Buffer libwire::tcp::socket::read ( size_t  bytes_count,
std::error_code &  ec 
)
noexcept

Same as overload with Buffer argument but return newly allocated buffer every time.

Definition at line 404 of file socket.hpp.

template<typename Buffer >
Buffer & libwire::tcp::socket::read_until ( uint8_t  delimiter,
Buffer &  buf,
std::error_code &  ec,
size_t  max_size = 0 
)
noexcept

Read from socket until until gives byte is found or max_size bytes read.

Note
Delimiter will be removed from socket stream but will not be appended to buffer.
max_size = 0 is a special case and means "no limit".

Buffer Type Requirements

size(), clear() and push_back() functions with behavior defined in SequenceContainer concept.

Definition at line 429 of file socket.hpp.

template<typename Buffer >
Buffer libwire::tcp::socket::read_until ( uint8_t  delimiter,
std::error_code &  ec,
size_t  max_size = 0 
)
noexcept

Same as overload with buffer argument but returns newly allocated buffer every time.

Definition at line 442 of file socket.hpp.

endpoint libwire::tcp::socket::remote_endpoint ( ) const
noexcept

Get address and port of remote end of connection.

Usually same as address/port passed in connect.

template<typename Option , typename... Args>
void libwire::tcp::socket::set_option ( const Option &  ,
Args &&...  args 
)
inlinenoexcept

Set socket option value specified by type tag Option to value value.

Setting option not supported on current platform or specifying invalid value results in undefined behavior. But usually new value just ignored and corresponding option(tag) will return old value.

Example:

socket.set_option(tcp::no_delay, true);
// Some options may have multiple values:
socket.set_option(tcp::linger, true, 20s);
// ^ enable linger with 20 seconds timeout.

Definition at line 182 of file socket.hpp.

void libwire::tcp::socket::shutdown ( bool  read = true,
bool  write = true 
)
noexcept

Shutdown reading/writing part of full-duplex connection (or both if read and write is true).

This function have no effect if socket is not connected ("Not connected" error is silently ignored).

If both read and write arguments set to false behavior is undefined.

Note
Socket can't be reused after shutdown, i.e. you can't do connect after shutdown.
template<typename Buffer >
size_t libwire::tcp::socket::write ( const Buffer &  input,
std::error_code &  ec 
)
noexcept

Write contents of buffer to socket.

Error code will be set if anything went wrong.

Returns actual amount of bytes written, usually same as buffer size unless socket is in non-blocking mode.

Buffer type requirements

Buffer must be container that encapsulates dynamic array, so it must have data and size member functions with behavior as in std::vector.

Definition at line 416 of file socket.hpp.