18 Sockets [socket]

18.1 Header <experimental/socket> synopsis [socket.synop]

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  enum class socket_errc {
    already_open = an implementation-defined non-zero value,
    not_found = an implementation-defined non-zero value
  };

  const error_category& socket_category() noexcept;

  error_code make_error_code(socket_errc e) noexcept;
  error_condition make_error_condition(socket_errc e) noexcept;

  // Sockets:

  class socket_base;

  template<class Protocol>
    class basic_socket;

  template<class Protocol>
    class basic_datagram_socket;

  template<class Protocol>
    class basic_stream_socket;

  template<class Protocol>
    class basic_socket_acceptor;

  // [socket.iostreams], Socket streams:

  template<class Protocol, class Clock = chrono::steady_clock,
    class WaitTraits = wait_traits<Clock>>
      class basic_socket_streambuf;

  template<class Protocol, class Clock = chrono::steady_clock,
    class WaitTraits = wait_traits<Clock>>
      class basic_socket_iostream;

  // [socket.algo.connect], synchronous connect operations:

  template<class Protocol, class EndpointSequence>
    typename Protocol::endpoint connect(basic_socket<Protocol>& s,
                                        const EndpointSequence& endpoints);
  template<class Protocol, class EndpointSequence>
    typename Protocol::endpoint connect(basic_socket<Protocol>& s,
                                        const EndpointSequence& endpoints,
                                        error_code& ec);
  template<class Protocol, class EndpointSequence, class ConnectCondition>
    typename Protocol::endpoint connect(basic_socket<Protocol>& s,
                                        const EndpointSequence& endpoints,
                                        ConnectCondition c);
  template<class Protocol, class EndpointSequence, class ConnectCondition>
    typename Protocol::endpoint connect(basic_socket<Protocol>& s,
                                        const EndpointSequence& endpoints,
                                        ConnectCondition c,
                                        error_code& ec);

  template<class Protocol, class InputIterator>
    InputIterator connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last);
  template<class Protocol, class InputIterator>
    InputIterator connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last,
                          error_code& ec);
  template<class Protocol, class InputIterator, class ConnectCondition>
    InputIterator connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last,
                          ConnectCondition c);
  template<class Protocol, class InputIterator, class ConnectCondition>
    InputIterator connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last,
                          ConnectCondition c,
                          error_code& ec);

  // [socket.algo.async.connect], asynchronous connect operations:

  template<class Protocol, class EndpointSequence, class CompletionToken>
    DEDUCED async_connect(basic_socket<Protocol>& s,
                          const EndpointSequence& endpoints,
                          CompletionToken&& token);
  template<class Protocol, class EndpointSequence, class ConnectCondition,
           class CompletionToken>
    DEDUCED async_connect(basic_socket<Protocol>& s,
                          const EndpointSequence& endpoints,
                          ConnectCondition c,
                          CompletionToken&& token);

  template<class Protocol, class InputIterator, class CompletionToken>
    DEDUCED async_connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last,
                          CompletionToken&& token);
  template<class Protocol, class InputIterator, class ConnectCondition,
           class CompletionToken>
    DEDUCED async_connect(basic_socket<Protocol>& s,
                          InputIterator first, InputIterator last,
                          ConnectCondition c,
                          CompletionToken&& token);

} // inline namespace v1
} // namespace net
} // namespace experimental

  template<> struct is_error_code_enum<experimental::net::v1::socket_errc>
    : public true_type {};

} // namespace std

The figure below illustrates relationships between various types described in this document. A solid line from A to B that is terminated by an open arrow indicates that A is derived from B. A solid line from A to B that starts with a diamond and is terminated by a solid arrow indicates that A contains an object of type B. A dotted line from A to B indicates that A is a synonym for the class template B with the specified template argument.

image/svg+xml
Figure 1 — Socket and socket stream types [non-normative]

18.2 Requirements [socket.reqmts]

18.2.1 Requirements on synchronous socket operations [socket.reqmts.sync]

In this subclause, synchronous socket operations are those member functions specified as two overloads, with and without an argument of type error_code&:

R f(A1 a1, A2 a2, ..., AN aN);
R f(A1 a1, A2 a2, ..., AN aN, error_code& ec);

For an object s, the conditions under which its synchronous socket operations may block the calling thread (C++ 2014 [defns.block]) are determined as follows.

If:

  • s.non_blocking() == true,

  • the synchronous socket operation is specified in terms of a POSIX function other than poll,

  • that POSIX function lists EWOULDBLOCK or EAGAIN in its failure conditions, and

  • the effects of the operation cannot be established immediately

then the synchronous socket operation shall not block the calling thread. [ Note: And the effects of the operation are not established.  — end note ]

Otherwise, the synchronous socket operation shall block the calling thread until the effects are established.

18.2.2 Requirements on asynchronous socket operations [socket.reqmts.async]

In this subclause, asynchronous socket operations are those member functions having prefix async_.

For an object s, a program may initiate asynchronous socket operations such that there are multiple simultaneously outstanding asynchronous operations.

When there are multiple outstanding asynchronous read operations ([buffer.reqmts.read.write]) on s:

  • having no argument flags of type socket_base::message_flags, or

  • having an argument flags of type socket_base::message_flags but where (flags & socket_base::message_out_of_band) == 0

then the buffers are filled in the order in which these operations were issued. The order of invocation of the completion handlers for these operations is unspecified.

When there are multiple outstanding asynchronous read operations ([buffer.reqmts.read.write]) on s having an argument flags of type socket_base::message_flags where (flags & socket_base::message_out_of_band) != 0 then the buffers are filled in the order in which these operations were issued.

When there are multiple outstanding asynchronous write operations ([buffer.reqmts.read.write]) on s, the buffers are transmitted in the order in which these operations were issued. The order of invocation of the completion handlers for these operations is unspecified.

18.2.3 Native handles [socket.reqmts.native]

Several classes described in this document have a member type native_handle_type, a member function native_handle, and member functions that return or accept arguments of type native_handle_type. The presence of these members and their semantics is implementation-defined.

When an operation has its effects specified as if by passing the result of native_handle() to a POSIX function the effect is as if native_handle_type is the type int.

Note: These members allow implementations to provide access to their implementation details. Their names are specified to facilitate portable compile-time detection. Actual use of these members is inherently non-portable. For operating systems that are based on POSIX, implementations can define the native_handle_type for sockets as int, representing the native file descriptor associated with the socket.  — end note ]

18.2.4 Endpoint requirements [socket.reqmts.endpoint]

A type X meets the Endpoint requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]), DefaultConstructible (C++ 2014 [defaultconstructible]), CopyConstructible (C++ 2014 [copyconstructible]), and CopyAssignable (C++ 2014 [copyassignable]), as well as the additional requirements listed below.

In the table below, a denotes a (possibly const) value of type X, and u denotes an identifier.

Table 21 — Endpoint requirements
expressiontypeassertion/note pre/post-conditions
X::protocol_type type meeting Protocol ([socket.reqmts.protocol]) requirements
a.protocol() protocol_type

In the table below, a denotes a (possibly const) value of type X, b denotes a value of type X, and s denotes a (possibly const) value of a type that is convertible to size_t and denotes a size in bytes.

Table 22 — Endpoint requirements for extensible implementations
expressiontypeassertion/note pre/post-conditions
a.data() const void* Returns a pointer suitable for passing as the address argument to functions such as POSIX connect, or as the dest_addr argument to functions such as POSIX sendto. The implementation shall perform a static_cast on the pointer to convert it to const sockaddr*.
b.data() void* Returns a pointer suitable for passing as the address argument to functions such as POSIX accept, getpeername, getsockname and recvfrom. The implementation shall perform a static_cast on the pointer to convert it to sockaddr*.
a.size() size_t Returns a value suitable for passing as the address_len argument to functions such as POSIX connect, or as the dest_len argument to functions such as POSIX sendto, after appropriate integer conversion has been performed.
b.resize(s) pre: s >= 0
post: a.size() == s
Passed the value contained in the address_len argument to functions such as POSIX accept, getpeername, getsockname, and recvfrom, after successful completion of the function. Permitted to throw an exception if the protocol associated with the endpoint object a does not support the specified size.
a.capacity() size_t Returns a value suitable for passing as the address_len argument to functions such as POSIX accept, getpeername, getsockname, and recvfrom, after appropriate integer conversion has been performed.

18.2.5 Endpoint sequence requirements [socket.reqmts.endpointsequence]

A type X meets the EndpointSequence requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed below.

In the table below, x denotes a (possibly const) value of type X.

Table 23 — EndpointSequence requirements
expressionreturn typeassertion/note pre/post-condition
x.begin()
x.end()
A type meeting the requirements for forward iterators (C++ 2014 [forward.iterators]) whose value type is convertible to a type satisfying the Endpoint ([socket.reqmts.endpoint]) requirements. [x.begin(), x.end()) is a valid range.

18.2.6 Protocol requirements [socket.reqmts.protocol]

A type X meets the Protocol requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]), CopyConstructible (C++ 2014 [copyconstructible]), and CopyAssignable (C++ 2014 [copyassignable]), as well as the additional requirements listed below.

Table 24 — Protocol requirements
expressionreturn typeassertion/note pre/post-conditions
X::endpoint type meeting endpoint ([socket.reqmts.endpoint]) requirements

In the table below, a denotes a (possibly const) value of type X.

Table 25 — Protocol requirements for extensible implementations
expressionreturn typeassertion/note pre/post-conditions
a.family() int Returns a value suitable for passing as the domain argument to POSIX socket (or equivalent).
a.type() int Returns a value suitable for passing as the type argument to POSIX socket (or equivalent).
a.protocol() int Returns a value suitable for passing as the protocol argument to POSIX socket (or equivalent).

18.2.7 Acceptable protocol requirements [socket.reqmts.acceptableprotocol]

A type X meets the AcceptableProtocol requirements if it satisfies the requirements of Protocol ([socket.reqmts.protocol]) as well as the additional requirements listed below.

Table 26 — AcceptableProtocol requirements
expressionreturn typeassertion/note pre/post-conditions
X::socket A type that satisfies the requirements of Destructible (C++ 2014 [destructible]) and MoveConstructible (C++ 2014 [moveconstructible]), and that is publicly and unambiguously derived from basic_socket<X>.

18.2.8 Gettable socket option requirements [socket.reqmts.gettablesocketoption]

A type X meets the GettableSocketOption requirements if it satisfies the requirements listed below.

In the table below, a denotes a (possibly const) value of type X, b denotes a value of type X, p denotes a value of a (possibly const) type that meets the Protocol ([socket.reqmts.protocol]) requirements, and s denotes a value of a (possibly const) type that is convertible to size_t and denotes a size in bytes.

Table 27 — GettableSocketOption requirements for extensible implementations
expressiontypeassertion/note pre/post-conditions
a.level(p) int Returns a value suitable for passing as the level argument to POSIX getsockopt (or equivalent).
a.name(p) int Returns a value suitable for passing as the option_name argument to POSIX getsockopt (or equivalent).
b.data(p) void* Returns a pointer suitable for passing as the option_value argument to POSIX getsockopt (or equivalent).
a.size(p) size_t Returns a value suitable for passing as the option_len argument to POSIX getsockopt (or equivalent), after appropriate integer conversion has been performed.
b.resize(p,s) post: b.size(p) == s. Passed the value contained in the option_len argument to POSIX getsockopt (or equivalent) after successful completion of the function. Permitted to throw an exception if the socket option object b does not support the specified size.

18.2.9 Settable socket option requirements [socket.reqmts.settablesocketoption]

A type X meets the SettableSocketOption requirements if it satisfies the requirements listed below.

In the table below, a denotes a (possibly const) value of type X, p denotes a (possibly const) value of a type that meets the Protocol ([socket.reqmts.protocol]) requirements, and u denotes an identifier.

Table 28 — SettableSocketOption requirements for extensible implementations
expressiontypeassertion/note pre/post-conditions
a.level(p) int Returns a value suitable for passing as the level argument to POSIX setsockopt (or equivalent).
a.name(p) int Returns a value suitable for passing as the option_name argument to POSIX setsockopt (or equivalent).
a.data(p) const void* Returns a pointer suitable for passing as the option_value argument to POSIX setsockopt (or equivalent).
a.size(p) size_t Returns a value suitable for passing as the option_len argument to POSIX setsockopt (or equivalent), after appropriate integer conversion has been performed.

18.2.10 Boolean socket options [socket.reqmts.opt.bool]

A type X meets the BooleanSocketOption requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]), DefaultConstructible (C++ 2014 [defaultconstructible]), CopyConstructible (C++ 2014 [copyconstructible]), CopyAssignable (C++ 2014 [copyassignable]), GettableSocketOption ([socket.reqmts.gettablesocketoption]), and SettableSocketOption ([socket.reqmts.settablesocketoption]), X is contextually convertible to bool, and X satisfies the additional requirements listed below.

In the table below, a denotes a (possibly const) value of type X, v denotes a (possibly const) value of type bool, and u denotes an identifier.

Table 29 — BooleanSocketOption requirements
expressiontypeassertion/note pre/post-conditions
X u; post: !u.value().
X u(v); post: u.value() == v.
a.value() bool Returns the current boolean value of the socket option object.
static_cast<bool>(a) bool Returns a.value().
!a bool Returns !a.value().

In this document, types that satisfy the BooleanSocketOption requirements are defined as follows.

class C{
public:
  // constructors:
  C() noexcept;
  explicit C(bool v) noexcept;

  // members:
  C& operator=(bool v) noexcept;

  bool value() const noexcept;

  explicit operator bool() const noexcept;
  bool operator!() const noexcept;
};

Extensible implementations provide the following member functions:

class C{
public:
  template<class Protocol> int level(const Protocol& p) const noexcept;
  template<class Protocol> int name(const Protocol& p) const noexcept;
  template<class Protocol> void* data(const Protocol& p) noexcept;
  template<class Protocol> const void* data(const Protocol& p) const noexcept;
  template<class Protocol> size_t size(const Protocol& p) const noexcept;
  template<class Protocol> void resize(const Protocol& p, size_t s);
  // remainder unchanged
private:
  int value_; // exposition only
};

Let L and N identify the POSIX macros to be passed as the level and option_name arguments, respectively, to POSIX setsockopt and getsockopt.

C() noexcept;

Postconditions: !value().

explicit C(bool v) noexcept;

Postconditions: value() == v.

C& operator=(bool v) noexcept;

Returns: *this.

Postconditions: value() == v.

bool value() const noexcept;

Returns: The stored socket option value. For extensible implementations, returns value_ != 0.

explicit operator bool() const noexcept;

Returns: value().

bool operator!() const noexcept;

Returns: !value().

template<class Protocol> int level(const Protocol& p) const noexcept;

Returns: L.

template<class Protocol> int name(const Protocol& p) const noexcept;

Returns: N.

template<class Protocol> void* data(const Protocol& p) noexcept;

Returns: std::addressof(value_).

template<class Protocol> const void* data(const Protocol& p) const noexcept;

Returns: std::addressof(value_).

template<class Protocol> size_t size(const Protocol& p) const noexcept;

Returns: sizeof(value_).

template<class Protocol> void resize(const Protocol& p, size_t s);

Remarks: length_error if s is not a valid data size for the protocol specified by p.

18.2.11 Integer socket options [socket.reqmts.opt.int]

A type X meets the IntegerSocketOption requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]), DefaultConstructible (C++ 2014 [defaultconstructible]), CopyConstructible (C++ 2014 [copyconstructible]), CopyAssignable (C++ 2014 [copyassignable]), GettableSocketOption ([socket.reqmts.gettablesocketoption]), and SettableSocketOption ([socket.reqmts.settablesocketoption]), as well as the additional requirements listed below.

In the table below, a denotes a (possibly const) value of type X, v denotes a (possibly const) value of type int, and u denotes an identifier.

Table 30 — IntegerSocketOption requirements
expressiontypeassertion/note pre/post-conditions
X u; post: u.value() == 0.
X u(v); post: u.value() == v.
a.value() int Returns the current integer value of the socket option object.

In this document, types that satisfy the IntegerSocketOption requirements are defined as follows.

class C{
public:
  // constructors:
  C() noexcept;
  explicit C(int v) noexcept;

  // members:
  C& operator=(int v) noexcept;

  int value() const noexcept;
};

Extensible implementations provide the following member functions:

class C{
public:
  template<class Protocol> int level(const Protocol& p) const noexcept;
  template<class Protocol> int name(const Protocol& p) const noexcept;
  template<class Protocol> void* data(const Protocol& p) noexcept;
  template<class Protocol> const void* data(const Protocol& p) const noexcept;
  template<class Protocol> size_t size(const Protocol& p) const noexcept;
  template<class Protocol> void resize(const Protocol& p, size_t s);
  // remainder unchanged
private:
  int value_; // exposition only
};

Let L and N identify the POSIX macros to be passed as the level and option_name arguments, respectively, to POSIX setsockopt and getsockopt.

C() noexcept;

Postconditions: !value().

explicit C(int v) noexcept;

Postconditions: value() == v.

C& operator=(int v) noexcept;

Returns: *this.

Postconditions: value() == v.

int value() const noexcept;

Returns: The stored socket option value. For extensible implementations, returns value_.

template<class Protocol> int level(const Protocol& p) const noexcept;

Returns: L.

template<class Protocol> int name(const Protocol& p) const noexcept;

Returns: N.

template<class Protocol> void* data(const Protocol& p) noexcept;

Returns: std::addressof(value_).

template<class Protocol> const void* data(const Protocol& p) const noexcept;

Returns: std::addressof(value_).

template<class Protocol> size_t size(const Protocol& p) const noexcept;

Returns: sizeof(value_).

template<class Protocol> void resize(const Protocol& p, size_t s);

Remarks: length_error if s is not a valid data size for the protocol specified by p.

18.2.12 I/O control command requirements [socket.reqmts.iocontrolcommand]

A type X meets the IoControlCommand requirements if it satisfies the requirements listed below.

In the table below, a denotes a (possibly const) value of type X, and b denotes a value of type X.

Table 31 — IoControlCommand requirements for extensible implementations
expressiontypeassertion/note pre/post-conditions
a.name() int Returns a value suitable for passing as the request argument to POSIX ioctl (or equivalent).
b.data() void*

18.2.13 Connect condition requirements [socket.reqmts.connectcondition]

A type X meets the ConnectCondition requirements if it satisfies the requirements of Destructible (C++ 2014 [destructible]) and CopyConstructible (C++ 2014 [copyconstructible]), as well as the additional requirements listed below.

In the table below, x denotes a value of type X, ec denotes a (possibly const) value of type error_code, and ep denotes a (possibly const) value of a type satisfying the endpoint ([socket.reqmts.endpoint]) requirements.

Table 32 — ConnectCondition requirements
expressionreturn typeassertion/note pre/post-condition
x(ec, ep) bool Returns true to indicate that the connect or async_connect algorithm should attempt a connection to the endpoint ep. Otherwise, returns false to indicate that the algorithm should not attempt connection to the endpoint ep, and should instead skip to the next endpoint in the sequence.

18.3 Error codes [socket.err]

const error_category& socket_category() noexcept;

Returns: A reference to an object of a type derived from class error_category. All calls to this function return references to the same object.

The object's default_error_condition and equivalent virtual functions behave as specified for the class error_category. The object's name virtual function returns a pointer to the string "socket".

error_code make_error_code(socket_errc e) noexcept;

Returns: error_code(static_cast<int>(e), socket_category()).

error_condition make_error_condition(socket_errc e) noexcept;

Returns: error_condition(static_cast<int>(e), socket_category()).

18.4 Class socket_base [socket.base]

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class socket_base
  {
  public:
    class broadcast;
    class debug;
    class do_not_route;
    class keep_alive;
    class linger;
    class out_of_band_inline;
    class receive_buffer_size;
    class receive_low_watermark;
    class reuse_address;
    class send_buffer_size;
    class send_low_watermark;

    using shutdown_type = T1;
    static constexpr shutdown_type shutdown_receive;
    static constexpr shutdown_type shutdown_send;
    static constexpr shutdown_type shutdown_both;

    using wait_type = T2;
    static constexpr wait_type wait_read;
    static constexpr wait_type wait_write;
    static constexpr wait_type wait_error;

    using message_flags = T3;
    static constexpr message_flags message_peek;
    static constexpr message_flags message_out_of_band;
    static constexpr message_flags message_do_not_route;

    static const int max_listen_connections;

  protected:
    socket_base();
    ~socket_base();
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

socket_base defines several member types:

  • socket option classes broadcast, debug, do_not_route, keep_alive, linger, out_of_band_inline, receive_buffer_size, receive_low_watermark, reuse_address, send_buffer_size, and send_low_watermark;

  • an enumerated type, shutdown_type, for use with the basic_socket<Protocol> class's shutdown member function.

  • an enumerated type, wait_type, for use with the basic_socket<Protocol> and basic_socket_acceptor<Protocol> classes' wait and async_wait member functions,

  • a bitmask type, message_flags, for use with the basic_stream_socket<Protocol> class's send, async_send, receive, and async_receive member functions, and the basic_datagram_socket<Protocol> class's send, async_send, send_to, async_send_to, receive, async_receive, receive_from, and async_receive_from member functions.

  • a constant, max_listen_connections, for use with the basic_socket_acceptor<Protocol> class's listen member function.

Table 33socket_base constants
Constant NamePOSIX macroDefinition or notes
shutdown_receive SHUT_RD Disables further receive operations.
shutdown_send SHUT_WR Disables further send operations.
shutdown_both SHUT_RDWR Disables further send and receive operations.
wait_read Wait until the socket is ready-to-read. For a given socket, when a wait or async_wait operation using wait_read completes successfully, a subsequent call to the socket's receive or receive_from functions may complete without blocking. Similarly, for a given acceptor, when a wait or async_wait operation using wait_read completes successfully, a subsequent call to the acceptor's accept function may complete without blocking.
wait_write Wait until the socket is ready-to-write. For a given socket, when a wait or async_wait operation using wait_write completes successfully, a subsequent call to the socket's send or send_to functions may complete without blocking.
wait_error Wait until the socket has a pending error condition. For a given socket, when a wait or async_wait operation using wait_error completes successfully, a subsequent call to one of the socket's synchronous operations may complete without blocking. The nature of the pending error condition determines which.
message_peek MSG_PEEK Leave received data in queue.
message_out_of_band MSG_OOB Out-of-band data.
message_do_not_route MSG_DONTROUTE Send without using routing tables.
max_listen_connections SOMAXCONN The implementation-defined limit on the length of the queue of pending incoming connections.

18.5 Socket options [socket.opt]

In the table below, let C denote a socket option class; let L identify the POSIX macro to be passed as the level argument to POSIX setsockopt and getsockopt; let N identify the POSIX macro to be passed as the option_name argument to POSIX setsockopt and getsockopt; and let T identify the type of the value whose address will be passed as the option_value argument to POSIX setsockopt and getsockopt.

Table 34 — Socket options
CLNTRequirements, definition or notes
socket_base:: broadcast SOL_SOCKET SO_BROADCAST int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether a socket permits sending of broadcast messages, if supported by the protocol.
socket_base:: debug SOL_SOCKET SO_DEBUG int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether debugging information is recorded by the underlying protocol.
socket_base:: do_not_route SOL_SOCKET SO_DONTROUTE int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether outgoing messages bypass standard routing facilities.
socket_base:: keep_alive SOL_SOCKET SO_KEEPALIVE int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether a socket permits sending of keep_alive messages, if supported by the protocol.
socket_base:: linger ([socket.opt.linger]) SOL_SOCKET SO_LINGER linger Controls the behavior when a socket is closed and unsent data is present.
socket_base:: out_of_band_inline SOL_SOCKET SO_OOBINLINE int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether out-of-band data (also known as urgent data) is received inline.
socket_base:: receive_buffer_size SOL_SOCKET SO_RCVBUF int Satisfies the IntegerSocketOption ([socket.reqmts.opt.int]) type requirements. Specifies the size of the receive buffer associated with a socket.
socket_base:: receive_low_watermark SOL_SOCKET SO_RCVLOWAT int Satisfies the IntegerSocketOption ([socket.reqmts.opt.int]) type requirements. Specifies the minimum number of bytes to process for socket input operations.
socket_base:: reuse_address SOL_SOCKET SO_REUSEADDR int Satisfies the BooleanSocketOption ([socket.reqmts.opt.bool]) type requirements. Determines whether the validation of endpoints used for binding a socket should allow the reuse of local endpoints, if supported by the protocol.
socket_base:: send_buffer_size SOL_SOCKET SO_SNDBUF int Satisfies the IntegerSocketOption ([socket.reqmts.opt.int]) type requirements. Specifies the size of the send buffer associated with a socket.
socket_base:: send_low_watermark SOL_SOCKET SO_SNDLOWAT int Satisfies the IntegerSocketOption ([socket.reqmts.opt.int]) type requirements. Specifies the minimum number of bytes to process for socket output operations.

18.5.1 Class socket_base::linger [socket.opt.linger]

The linger class represents a socket option for controlling the behavior when a socket is closed and unsent data is present.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class socket_base::linger
  {
  public:
    // constructors:
    linger() noexcept;
    linger(bool e, chrono::seconds t) noexcept;

    // members:
    bool enabled() const noexcept;
    void enabled(bool e) noexcept;

    chrono::seconds timeout() const noexcept;
    void timeout(chrono::seconds t) noexcept;
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

linger satisfies the requirements of Destructible (C++ 2014 [destructible]), DefaultConstructible (C++ 2014 [defaultconstructible]), CopyConstructible (C++ 2014 [copyconstructible]), CopyAssignable (C++ 2014 [copyassignable]), GettableSocketOption ([socket.reqmts.gettablesocketoption]), and SettableSocketOption ([socket.reqmts.settablesocketoption]).

Extensible implementations provide the following member functions:

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class socket_base::linger
  {
  public:
    template<class Protocol> int level(const Protocol& p) const noexcept;
    template<class Protocol> int name(const Protocol& p) const noexcept;
    template<class Protocol> void data(const Protocol& p) noexcept;
    template<class Protocol> const void* data(const Protocol& p) const noexcept;
    template<class Protocol> size_t size(const Protocol& p) const noexcept;
    template<class Protocol> void resize(const Protocol& p, size_t s);
    // remainder unchanged
  private:
    ::linger value_;  // exposition only
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

linger() noexcept;

Postconditions: !enabled() && timeout() == chrono::seconds(0).

linger(bool e, chrono::seconds t) noexcept;

Postconditions: enabled() == e && timeout() == t.

bool enabled() const noexcept;

Returns: value_.l_onoff != 0.

void enabled(bool e) noexcept;

Postconditions: enabled() == e.

chrono::seconds timeout() const noexcept;

Returns: chrono::seconds(value_.l_linger).

void timeout(chrono::seconds t) noexcept;

Postconditions: timeout() == t.

template<class Protocol> int level(const Protocol& p) const noexcept;

Returns: SOL_SOCKET.

template<class Protocol> int name(const Protocol& p) const noexcept;

Returns: SO_LINGER.

template<class Protocol> void* data(const Protocol& p) const noexcept;

Returns: std::addressof(value_).

template<class Protocol> const void* data(const Protocol& p) const noexcept;

Returns: std::addressof(value_).

template<class Protocol> size_t size(const Protocol& p) const noexcept;

Returns: sizeof(value_).

template<class Protocol> void resize(const Protocol& p, size_t s);

Remarks: length_error if s != sizeof(value_).

18.6 Class template basic_socket [socket.basic]

Class template basic_socket<Protocol> is used as the base class for the basic_datagram_socket<Protocol> and basic_stream_socket<Protocol> class templates. It provides functionality that is common to both types of socket.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  template<class Protocol>
  class basic_socket : public socket_base
  {
  public:
    // types:

    using executor_type = io_context::executor_type;
    using native_handle_type = implementation-defined; // see [socket.reqmts.native]
    using protocol_type = Protocol;
    using endpoint_type = typename protocol_type::endpoint;

    // [socket.basic.ops], basic_socket operations:

    executor_type get_executor() noexcept;

    native_handle_type native_handle(); // see [socket.reqmts.native]

    void open(const protocol_type& protocol = protocol_type());
    void open(const protocol_type& protocol, error_code& ec);

    void assign(const protocol_type& protocol,
                const native_handle_type& native_socket); // see [socket.reqmts.native]
    void assign(const protocol_type& protocol,
                const native_handle_type& native_socket,
                error_code& ec); // see [socket.reqmts.native]

    native_handle_type release(); // see [socket.reqmts.native]
    native_handle_type release(error_code& ec); // see [socket.reqmts.native]

    bool is_open() const noexcept;

    void close();
    void close(error_code& ec);

    void cancel();
    void cancel(error_code& ec);

    template<class SettableSocketOption>
      void set_option(const SettableSocketOption& option);
    template<class SettableSocketOption>
      void set_option(const SettableSocketOption& option, error_code& ec);

    template<class GettableSocketOption>
      void get_option(GettableSocketOption& option) const;
    template<class GettableSocketOption>
      void get_option(GettableSocketOption& option, error_code& ec) const;

    template<class IoControlCommand>
      void io_control(IoControlCommand& command);
    template<class IoControlCommand>
      void io_control(IoControlCommand& command, error_code& ec);

    void non_blocking(bool mode);
    void non_blocking(bool mode, error_code& ec);
    bool non_blocking() const;

    void native_non_blocking(bool mode);
    void native_non_blocking(bool mode, error_code& ec);
    bool native_non_blocking() const;

    bool at_mark() const;
    bool at_mark(error_code& ec) const;

    size_t available() const;
    size_t available(error_code& ec) const;

    void bind(const endpoint_type& endpoint);
    void bind(const endpoint_type& endpoint, error_code& ec);

    void shutdown(shutdown_type what);
    void shutdown(shutdown_type what, error_code& ec);

    endpoint_type local_endpoint() const;
    endpoint_type local_endpoint(error_code& ec) const;

    endpoint_type remote_endpoint() const;
    endpoint_type remote_endpoint(error_code& ec) const;

    void connect(const endpoint_type& endpoint);
    void connect(const endpoint_type& endpoint, error_code& ec);

    template<class CompletionToken>
      DEDUCED async_connect(const endpoint_type& endpoint,
                            CompletionToken&& token);

    void wait(wait_type w);
    void wait(wait_type w, error_code& ec);

    template<class CompletionToken>
      DEDUCED async_wait(wait_type w, CompletionToken&& token);

  protected:
    // [socket.basic.cons], construct / copy / destroy:

    explicit basic_socket(io_context& ctx);
    basic_socket(io_context& ctx, const protocol_type& protocol);
    basic_socket(io_context& ctx, const endpoint_type& endpoint);
    basic_socket(io_context& ctx, const protocol_type& protocol,
                 const native_handle_type& native_socket); // see [socket.reqmts.native]
    basic_socket(const basic_socket&) = delete;
    basic_socket(basic_socket&& rhs);
    template<class OtherProtocol>
      basic_socket(basic_socket<OtherProtocol>&& rhs);

    ~basic_socket();

    basic_socket& operator=(const basic_socket&) = delete;
    basic_socket& operator=(basic_socket&& rhs);
    template<class OtherProtocol>
      basic_socket& operator=(basic_socket<OtherProtocol>&& rhs);

  private:
    protocol_type protocol_; // exposition only
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

Instances of class template basic_socket meet the requirements of Destructible (C++ 2014 [destructible]), MoveConstructible (C++ 2014 [moveconstructible]), and MoveAssignable (C++ 2014 [moveassignable]).

When an operation has its effects specified as if by passing the result of native_handle() to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false at the point in the effects when the POSIX function is called.

18.6.1 basic_socket constructors [socket.basic.cons]

explicit basic_socket(io_context& ctx);

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == false.

basic_socket(io_context& ctx, const protocol_type& protocol);

Effects: Opens this socket as if by calling open(protocol).

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • protocol_ == protocol.

basic_socket(io_context& ctx, const endpoint_type& endpoint);

Effects: Opens and binds this socket as if by calling:

open(endpoint.protocol());
bind(endpoint);

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • protocol_ == endpoint.protocol().

basic_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);

Requires: native_socket is a native handle to an open socket.

Effects: Assigns the existing native socket into this socket as if by calling assign(protocol, native_socket).

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • protocol_ == protocol.

basic_socket(basic_socket&& rhs);

Effects: Move constructs an object of class basic_socket<Protocol> that refers to the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the constructor invocation.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the constructor invocation.

  • native_handle() returns the prior value of rhs.native_handle().

  • protocol_ is the prior value of rhs.protocol_.

  • rhs.is_open() == false.

template<class OtherProtocol> basic_socket(basic_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Move constructs an object of class basic_socket<Protocol> that refers to the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the constructor invocation.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the constructor invocation.

  • native_handle() returns the prior value of rhs.native_handle().

  • protocol_ is the result of converting the prior value of rhs.protocol_.

  • rhs.is_open() == false.

Remarks: This constructor shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.6.2 basic_socket destructor [socket.basic.dtor]

~basic_socket();

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this socket, disables the linger socket option to prevent the destructor from blocking, and releases socket resources as if by POSIX close(native_handle()). Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true.

18.6.3 basic_socket assignment [socket.basic.assign]

basic_socket& operator=(basic_socket&& rhs);

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true. Disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIX close(native_handle()). Moves into *this the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the assignment.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the assignment.

  • protocol_ is the prior value of rhs.protocol_.

  • rhs.is_open() == false.

Returns: *this.

template<class OtherProtocol> basic_socket& operator=(basic_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true. Disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIX close(native_handle()). Moves into *this the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the assignment.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the assignment.

  • protocol_ is the result of converting the prior value of rhs.protocol_.

  • rhs.is_open() == false.

Returns: *this.

Remarks: This assignment operator shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.6.4 basic_socket operations [socket.basic.ops]

executor_type get_executor() noexcept;

Returns: The associated executor.

native_handle_type native_handle();

Returns: The native representation of this socket.

void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);

Effects: Establishes the postcondition, as if by POSIX:

socket(protocol.family(), protocol.type(), protocol.protocol());

Postconditions:

  • is_open() == true.

  • non_blocking() == false.

  • protocol_ == protocol.

Error conditions:

  • socket_errc::already_open — if is_open() == true.

void assign(const protocol_type& protocol, const native_handle_type& native_socket); void assign(const protocol_type& protocol, const native_handle_type& native_socket, error_code& ec);

Requires: native_socket is a native handle to an open socket.

Effects: Assigns the native socket handle to this socket object.

Postconditions:

  • is_open() == true.

  • non_blocking() == false.

  • protocol_ == protocol.

Error conditions:

  • socket_errc::already_open — if is_open() == true.

native_handle_type release(); native_handle_type release(error_code& ec);

Requires: is_open() == true.

Effects: Cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Returns: The native representation of this socket.

Postconditions: is_open() == false.

Remarks: Since the native socket is not closed prior to returning it, the caller is responsible for closing it.

bool is_open() const noexcept;

Returns: A bool indicating whether this socket was opened by a previous call to open or assign.

void close(); void close(error_code& ec);

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this socket, and establishes the postcondition as if by POSIX close(native_handle()). Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Postconditions: is_open() == false.

void cancel(); void cancel(error_code& ec);

Effects: Cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

Remarks: Does not block (C++ 2014 [defns.block]) the calling thread pending completion of the canceled operations.

template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);

Effects: Sets an option on this socket, as if by POSIX:

setsockopt(native_handle(), option.level(protocol_), option.name(protocol_),
           option.data(protocol_), option.size(protocol_));

template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);

Effects: Gets an option from this socket, as if by POSIX:

socklen_t option_len = option.size(protocol_);
int result = getsockopt(native_handle(), option.level(protocol_),
                        option.name(protocol_), option.data(protocol_),
                        &option_len);
if (result == 0)
  option.resize(option_len);

template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);

Effects: Executes an I/O control command on this socket, as if by POSIX:

ioctl(native_handle(), command.name(), command.data());

void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);

Effects: Sets the non-blocking mode of this socket. The non-blocking mode determines whether subsequent synchronous socket operations ([socket.reqmts.sync]) on *this block the calling thread.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

Postconditions: non_blocking() == mode.

Note: The non-blocking mode has no effect on the behavior of asynchronous operations.  — end note ]

bool non_blocking() const;

Returns: The non-blocking mode of this socket.

void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);

Effects: Sets the non-blocking mode of the underlying native socket, as if by POSIX:

int flags = fcntl(native_handle(), F_GETFL, 0);
if (flags >= 0){
  if (mode)
    flags |= O_NONBLOCK;
  else
    flags &= ~O_NONBLOCK;
  fcntl(native_handle(), F_SETFL, flags);
}

The native non-blocking mode has no effect on the behavior of the synchronous or asynchronous operations specified in this clause.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

  • errc::invalid_argument — if mode == false and non_blocking() == true. [ Note: As the combination does not make sense.  — end note ]

bool native_non_blocking() const;

Returns: The non-blocking mode of the underlying native socket.

Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to native_non_blocking. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the socket, by calling an operating system-specific function on the result of native_handle().

bool at_mark() const; bool at_mark(error_code& ec) const;

Effects: Determines if this socket is at the out-of-band data mark, as if by POSIX sockatmark(native_handle()). [ Note: The at_mark() function is used in conjunction with the socket_base::out_of_band_inline socket option.  — end note ]

Returns: A bool indicating whether this socket is at the out-of-band data mark. false if an error occurs.

size_t available() const; size_t available(error_code& ec) const;

Returns: An indication of the number of bytes that may be read without blocking, or 0 if an error occurs.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);

Effects: Binds this socket to the specified local endpoint, as if by POSIX:

bind(native_handle(), endpoint.data(), endpoint.size());

void shutdown(shutdown_type what); void shutdown(shutdown_type what, error_code& ec);

Effects: Shuts down all or part of a full-duplex connection for the socket, as if by POSIX:

shutdown(native_handle(), static_cast<int>(what));

endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;

Effects: Determines the locally-bound endpoint associated with the socket, as if by POSIX:

endpoint_type endpoint;
socklen_t endpoint_len = endpoint.capacity();
int result = getsockname(native_handle(), endpoint.data(), &endpoint_len);
if (result == 0)
  endpoint.resize(endpoint_len);

Returns: On success, endpoint. Otherwise endpoint_type().

endpoint_type remote_endpoint() const; endpoint_type remote_endpoint(error_code& ec) const;

Effects: Determines the remote endpoint associated with this socket, as if by POSIX:

endpoint_type endpoint;
socklen_t endpoint_len = endpoint.capacity();
int result = getpeername(native_handle(), endpoint.data(), &endpoint_len);
if (result == 0)
  endpoint.resize(endpoint_len);

Returns: On success, endpoint. Otherwise endpoint_type().

void connect(const endpoint_type& endpoint); void connect(const endpoint_type& endpoint, error_code& ec);

Effects: If is_open() is false, opens this socket by performing open(endpoint.protocol(), ec). If ec, returns with no further action. Connects this socket to the specified remote endpoint, as if by POSIX connect(native_handle(), endpoint.data(), endpoint.size()).

template<class CompletionToken> DEDUCED async_connect(const endpoint_type& endpoint, CompletionToken&& token);

Completion signature: void(error_code ec).

Effects: If is_open() is false, opens this socket by performing open(endpoint.protocol(), ec). If ec, the operation completes immediately with no further action. Initiates an asynchronous operation to connect this socket to the specified remote endpoint, as if by POSIX connect(native_handle(), endpoint.data(), endpoint.size()).

When an asynchronous connect operation on this socket is simultaneously outstanding with another asynchronous connect, read, or write operation on this socket, the behavior is undefined.

If a program performs a synchronous operation on this socket, other than close or cancel, while there is an outstanding asynchronous connect operation, the behavior is undefined.

void wait(wait_type w); void wait(wait_type w, error_code& ec);

Effects: Waits for this socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX poll.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token);

Completion signature: void(error_code ec).

Effects: Initiates an asynchronous operation to wait for this socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX poll.

When there are multiple outstanding asynchronous wait operations on this socket with the same wait_type value, all of these operations complete when this socket enters the corresponding ready state. The order of invocation of the completion handlers for these operations is unspecified.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

18.7 Class template basic_datagram_socket [socket.dgram]

The class template basic_datagram_socket<Protocol> is used to send and receive discrete messages of fixed maximum length.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  template<class Protocol>
  class basic_datagram_socket : public basic_socket<Protocol>
  {
  public:
    // types:

    using native_handle_type = implementation-defined; // see [socket.reqmts.native]
    using protocol_type = Protocol;
    using endpoint_type = typename protocol_type::endpoint;

    // [socket.dgram.cons], construct / copy / destroy:

    explicit basic_datagram_socket(io_context& ctx);
    basic_datagram_socket(io_context& ctx, const protocol_type& protocol);
    basic_datagram_socket(io_context& ctx, const endpoint_type& endpoint);
    basic_datagram_socket(io_context& ctx, const protocol_type& protocol,
                          const native_handle_type& native_socket);
    basic_datagram_socket(const basic_datagram_socket&) = delete;
    basic_datagram_socket(basic_datagram_socket&& rhs);
    template<class OtherProtocol>
      basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs);

    ~basic_datagram_socket();

    basic_datagram_socket& operator=(const basic_datagram_socket&) = delete;
    basic_datagram_socket& operator=(basic_datagram_socket&& rhs);
    template<class OtherProtocol>
      basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs);

    // [socket.dgram.op], basic_datagram_socket operations:

    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers);
    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     error_code& ec);

    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     socket_base::message_flags flags);
    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     socket_base::message_flags flags, error_code& ec);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive(const MutableBufferSequence& buffers,
                            CompletionToken&& token);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive(const MutableBufferSequence& buffers,
                            socket_base::message_flags flags,
                            CompletionToken&& token);

    template<class MutableBufferSequence>
      size_t receive_from(const MutableBufferSequence& buffers,
                          endpoint_type& sender);
    template<class MutableBufferSequence>
      size_t receive_from(const MutableBufferSequence& buffers,
                          endpoint_type& sender, error_code& ec);

    template<class MutableBufferSequence>
      size_t receive_from(const MutableBufferSequence& buffers,
                          endpoint_type& sender,
                          socket_base::message_flags flags);
    template<class MutableBufferSequence>
      size_t receive_from(const MutableBufferSequence& buffers,
                          endpoint_type& sender,
                          socket_base::message_flags flags,
                          error_code& ec);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive_from(const MutableBufferSequence& buffers,
                                 endpoint_type& sender,
                                 CompletionToken&& token);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive_from(const MutableBufferSequence& buffers,
                                 endpoint_type& sender,
                                 socket_base::message_flags flags,
                                 CompletionToken&& token);

    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers);
    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers, error_code& ec);

    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers,
                  socket_base::message_flags flags);
    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers,
                  socket_base::message_flags flags, error_code& ec);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send(const ConstBufferSequence& buffers,
                         CompletionToken&& token);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send(const ConstBufferSequence& buffers,
                         socket_base::message_flags flags,
                         CompletionToken&& token);

    template<class ConstBufferSequence>
      size_t send_to(const ConstBufferSequence& buffers,
                     const endpoint_type& recipient);
    template<class ConstBufferSequence>
      size_t send_to(const ConstBufferSequence& buffers,
                     const endpoint_type& recipient, error_code& ec);

    template<class ConstBufferSequence>
      size_t send_to(const ConstBufferSequence& buffers,
                     const endpoint_type& recipient,
                     socket_base::message_flags flags);
    template<class ConstBufferSequence>
      size_t send_to(const ConstBufferSequence& buffers,
                     const endpoint_type& recipient,
                     socket_base::message_flags flags, error_code& ec);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send_to(const ConstBufferSequence& buffers,
                            const endpoint_type& recipient,
                            CompletionToken&& token);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send_to(const ConstBufferSequence& buffers,
                            const endpoint_type& recipient,
                            socket_base::message_flags flags,
                            CompletionToken&& token);
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

Instances of class template basic_datagram_socket meet the requirements of Destructible (C++ 2014 [destructible]), MoveConstructible (C++ 2014 [moveconstructible]), and MoveAssignable (C++ 2014 [moveassignable]).

If a program performs a synchronous operation on this socket, other than close, cancel, shutdown, send, or send_to, while there is an outstanding asynchronous read operation, the behavior is undefined.

If a program performs a synchronous operation on this socket, other than close, cancel, shutdown, receive, or receive_from, while there is an outstanding asynchronous write operation, the behavior is undefined.

When an operation has its effects specified as if by passing the result of native_handle() to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false at the point in the effects when the POSIX function is called.

If native_handle_type and basic_socket<Protocol>::native_handle_type are both defined then they name the same type.

18.7.1 basic_datagram_socket constructors [socket.dgram.cons]

explicit basic_datagram_socket(io_context& ctx);

Effects: Initializes the base class with basic_socket<Protocol>(ctx).

basic_datagram_socket(io_context& ctx, const protocol_type& protocol);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, protocol).

basic_datagram_socket(io_context& ctx, const endpoint_type& endpoint);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, endpoint).

basic_datagram_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, protocol, native_socket).

basic_datagram_socket(basic_datagram_socket&& rhs);

Effects: Move constructs an object of class basic_datagram_socket<Protocol>, initializing the base class with basic_socket<Protocol>(std::move(rhs)).

template<class OtherProtocol> basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Move constructs an object of class basic_datagram_socket<Protocol>, initializing the base class with basic_socket<Protocol>(std::move(rhs)).

Remarks: This constructor shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.7.2 basic_datagram_socket assignment [socket.dgram.assign]

basic_datagram_socket& operator=(basic_datagram_socket&& rhs);

Effects: Equivalent to basic_socket<Protocol>::operator=(std::move(rhs)).

Returns: *this.

template<class OtherProtocol> basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Equivalent to basic_socket<Protocol>::operator=(std::move(rhs)).

Returns: *this.

Remarks: This assignment operator shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.7.3 basic_datagram_socket operations [socket.dgram.op]

template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);

Returns: receive(buffers, socket_base::message_flags(), ec).

template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);

A read operation ([buffer.reqmts.read.write]).

Effects: Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and reads data from this socket as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
recvmsg(native_handle(), &message, static_cast<int>(flags));

Returns: On success, the number of bytes received. Otherwise 0.

Note: This operation can be used with connection-mode or connectionless-mode sockets, but it is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data.  — end note ]

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);

Returns: async_receive(buffers, socket_base::message_flags(), std::forward<CompletionToken>(token)).

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to read data from this socket. Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then reads data as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
recvmsg(native_handle(), &message, static_cast<int>(flags));

If the operation completes successfully, n is the number of bytes received. Otherwise n is 0.

Note: This operation can be used with connection-mode or connectionless-mode sockets, but it is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data.  — end note ]

Error conditions:

  • errc::invalid_argument — if socket_base::message_peek is set in flags.

template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, error_code& ec);

Returns: receive_from(buffers, sender, socket_base::message_flags(), ec).

template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, error_code& ec);

A read operation ([buffer.reqmts.read.write]).

Effects: Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and reads data from this socket as if by POSIX:

msghdr message;
message.msg_name = sender.data();
message.msg_namelen = sender.capacity();
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
ssize_t result = recvmsg(native_handle(), &message, static_cast<int>(flags));
if (result >= 0)
  sender.resize(message.msg_namelen);

Returns: On success, the number of bytes received. Otherwise 0.

Note: This operation can be used with connection-mode or connectionless-mode sockets, but it is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data.  — end note ]

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, CompletionToken&& token);

Returns:

async_receive_from(buffers, sender, socket_base::message_flags(),
                   forward<CompletionToken>(token))

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, CompletionToken&& token);

A read operation ([buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to read data from this socket. Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then reads data as if by POSIX:

msghdr message;
message.msg_name = sender.data();
message.msg_namelen = sender.capacity();
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
ssize_t result = recvmsg(native_handle(), &message, static_cast<int>(flags));
if (result >= 0)
  sender.resize(message.msg_namelen);

If the operation completes successfully, n is the number of bytes received. Otherwise n is 0.

Note: This operation can be used with connection-mode or connectionless-mode sockets, but it is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data.  — end note ]

Error conditions:

  • errc::invalid_argument — if socket_base::message_peek is set in flags.

template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);

Returns: send(buffers, socket_base::message_flags(), ec).

template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);

A write operation ([buffer.reqmts.read.write]).

Effects: Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and writes data to this socket as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

Returns: On success, the number of bytes sent. Otherwise 0.

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token);

Returns:

async_send(buffers, socket_base::message_flags(), forward<CompletionToken>(token))

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);

A write operation ([buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to write data to this socket. Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then writes data as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

If the operation completes successfully, n is the number of bytes sent. Otherwise n is 0.

template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, error_code& ec);

Returns: send_to(buffers, recipient, socket_base::message_flags(), ec).

template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, socket_base::message_flags flags, error_code& ec);

A write operation ([buffer.reqmts.read.write]).

Effects: Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and writes data to this socket as if by POSIX:

msghdr message;
message.msg_name = recipient.data();
message.msg_namelen = recipient.size();
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

Returns: On success, the number of bytes sent. Otherwise 0.

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, CompletionToken&& token);

Returns:

async_send_to(buffers, recipient, socket_base::message_flags(),
              forward<CompletionToken>(token))

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, socket_base::message_flags flags, CompletionToken&& token);

A write operation ([buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to write data to this socket. Constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then writes data as if by POSIX:

msghdr message;
message.msg_name = recipient.data();
message.msg_namelen = recipient.size();
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

If the operation completes successfully, n is the number of bytes sent. Otherwise n is 0.

18.8 Class template basic_stream_socket [socket.stream]

The class template basic_stream_socket<Protocol> is used to exchange data with a peer over a sequenced, reliable, bidirectional, connection-mode byte stream.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  template<class Protocol>
  class basic_stream_socket : public basic_socket<Protocol>
  {
  public:
    // types:

    using native_handle_type = implementation-defined; // see [socket.reqmts.native]
    using protocol_type = Protocol;
    using endpoint_type = typename protocol_type::endpoint;

    // [socket.stream.cons], construct / copy / destroy:

    explicit basic_stream_socket(io_context& ctx);
    basic_stream_socket(io_context& ctx, const protocol_type& protocol);
    basic_stream_socket(io_context& ctx, const endpoint_type& endpoint);
    basic_stream_socket(io_context& ctx, const protocol_type& protocol,
                        const native_handle_type& native_socket);
    basic_stream_socket(const basic_stream_socket&) = delete;
    basic_stream_socket(basic_stream_socket&& rhs);
    template<class OtherProtocol>
      basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs);

    ~basic_stream_socket();

    basic_stream_socket& operator=(const basic_stream_socket&) = delete;
    basic_stream_socket& operator=(basic_stream_socket&& rhs);
    template<class OtherProtocol>
      basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs);

    // [socket.stream.ops], basic_stream_socket operations:

    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers);
    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     error_code& ec);

    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     socket_base::message_flags flags);
    template<class MutableBufferSequence>
      size_t receive(const MutableBufferSequence& buffers,
                     socket_base::message_flags flags, error_code& ec);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive(const MutableBufferSequence& buffers,
                            CompletionToken&& token);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_receive(const MutableBufferSequence& buffers,
                            socket_base::message_flags flags,
                            CompletionToken&& token);

    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers);
    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers, error_code& ec);

    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers,
                  socket_base::message_flags flags);
    template<class ConstBufferSequence>
      size_t send(const ConstBufferSequence& buffers,
                  socket_base::message_flags flags, error_code& ec);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send(const ConstBufferSequence& buffers,
                         CompletionToken&& token);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_send(const ConstBufferSequence& buffers,
                         socket_base::message_flags flags,
                         CompletionToken&& token);

    template<class MutableBufferSequence>
      size_t read_some(const MutableBufferSequence& buffers);
    template<class MutableBufferSequence>
      size_t read_some(const MutableBufferSequence& buffers,
                       error_code& ec);

    template<class MutableBufferSequence, class CompletionToken>
      DEDUCED async_read_some(const MutableBufferSequence& buffers,
                              CompletionToken&& token);

    template<class ConstBufferSequence>
      size_t write_some(const ConstBufferSequence& buffers);
    template<class ConstBufferSequence>
      size_t write_some(const ConstBufferSequence& buffers,
                        error_code& ec);

    template<class ConstBufferSequence, class CompletionToken>
      DEDUCED async_write_some(const ConstBufferSequence& buffers,
                               CompletionToken&& token);
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

Instances of class template basic_stream_socket meet the requirements of Destructible (C++ 2014 [destructible]), MoveConstructible (C++ 2014 [moveconstructible]), MoveAssignable (C++ 2014 [moveassignable]), SyncReadStream ([buffer.stream.reqmts.syncreadstream]), SyncWriteStream ([buffer.stream.reqmts.syncwritestream]), AsyncReadStream ([buffer.stream.reqmts.asyncreadstream]), and AsyncWriteStream ([buffer.stream.reqmts.asyncwritestream]).

If a program performs a synchronous operation on this socket, other than close, cancel, shutdown, or send, while there is an outstanding asynchronous read operation, the behavior is undefined.

If a program performs a synchronous operation on this socket, other than close, cancel, shutdown, or receive, while there is an outstanding asynchronous write operation, the behavior is undefined.

When an operation has its effects specified as if by passing the result of native_handle() to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false at the point in the effects when the POSIX function is called.

If native_handle_type and basic_socket<Protocol>::native_handle_type are both defined then they name the same type.

18.8.1 basic_stream_socket constructors [socket.stream.cons]

explicit basic_stream_socket(io_context& ctx);

Effects: Initializes the base class with basic_socket<Protocol>(ctx).

basic_stream_socket(io_context& ctx, const protocol_type& protocol);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, protocol).

basic_stream_socket(io_context& ctx, const endpoint_type& endpoint);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, endpoint).

basic_stream_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);

Effects: Initializes the base class with basic_socket<Protocol>(ctx, protocol, native_socket).

basic_stream_socket(basic_stream_socket&& rhs);

Effects: Move constructs an object of class basic_stream_socket<Protocol>, initializing the base class with basic_socket<Protocol>(std::move(rhs)).

template<class OtherProtocol> basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Move constructs an object of class basic_stream_socket<Protocol>, initializing the base class with basic_socket<Protocol>(std::move(rhs)).

Remarks: This constructor shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.8.2 basic_stream_socket assignment [socket.stream.assign]

basic_stream_socket& operator=(basic_stream_socket&& rhs);

Effects: Equivalent to basic_socket<Protocol>::operator=(std::move(rhs)).

Returns: *this.

template<class OtherProtocol> basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Equivalent to basic_socket<Protocol>::operator=(std::move(rhs)).

Returns: *this.

Remarks: This assignment operator shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.8.3 basic_stream_socket operations [socket.stream.ops]

template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);

Returns: receive(buffers, socket_base::message_flags(), ec).

template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);

A read operation ([buffer.reqmts.read.write]).

Effects: If buffer_size(buffers) == 0, returns immediately with no error. Otherwise, constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and reads data from this socket as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
recvmsg(native_handle(), &message, static_cast<int>(flags));

Returns: On success, the number of bytes received. Otherwise 0.

Error conditions:

  • stream_errc::eof — if there is no data to be received and the peer performed an orderly shutdown.

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);

Returns:

async_receive(buffers, socket_base::message_flags(), forward<CompletionToken>(token))

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);

A read operation ([buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to read data from this socket. If buffer_size(buffers) == 0, the asynchronous operation completes immediately with no error and n == 0. Otherwise, constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then reads data as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
recvmsg(native_handle(), &message, static_cast<int>(flags));

If the operation completes successfully, n is the number of bytes received. Otherwise n is 0.

Error conditions:

  • errc::invalid_argument — if socket_base::message_peek is set in flags.

  • stream_errc::eof — if there is no data to be received and the peer performed an orderly shutdown.

template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);

Returns: send(buffers, socket_base::message_flags(), ec).

template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);

A write operation ([buffer.reqmts.read.write]).

Effects: If buffer_size(buffers) == 0, returns immediately with no error. Otherwise, constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, and writes data to this socket as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

Returns: On success, the number of bytes sent. Otherwise 0.

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token);

Returns:

async_send(buffers, socket_base::message_flags(), forward<CompletionToken>(token))

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);

A write operation ([buffer.reqmts.read.write]).

Completion signature: void(error_code ec, size_t n).

Effects: Initiates an asynchronous operation to write data to this socket. If buffer_size(buffers) == 0, the asynchronous operation completes immediately with no error and n == 0. Otherwise, constructs an array iov of POSIX type struct iovec and length iovlen, corresponding to buffers, then writes data as if by POSIX:

msghdr message;
message.msg_name = nullptr;
message.msg_namelen = 0;
message.msg_iov = iov;
message.msg_iovlen = iovlen;
message.msg_control = nullptr;
message.msg_controllen = 0;
message.msg_flags = 0;
sendmsg(native_handle(), &message, static_cast<int>(flags));

If the operation completes successfully, n is the number of bytes sent. Otherwise n is 0.

template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers, error_code& ec);

Returns: receive(buffers, ec).

template<class MutableBufferSequence, class CompletionToken> DEDUCED async_read_some(const MutableBufferSequence& buffers, CompletionToken&& token);

Returns: async_receive(buffers, forward<CompletionToken>(token)).

template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers, error_code& ec);

Returns: send(buffers, ec).

template<class ConstBufferSequence, class CompletionToken> DEDUCED async_write_some(const ConstBufferSequence& buffers, CompletionToken&& token);

Returns: async_send(buffers, forward<CompletionToken>(token)).

18.9 Class template basic_socket_acceptor [socket.acceptor]

An object of class template basic_socket_acceptor<AcceptableProtocol> is used to listen for, and queue, incoming socket connections. Socket objects that represent the incoming connections are dequeued by calling accept or async_accept.

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  template<class AcceptableProtocol>
  class basic_socket_acceptor : public socket_base
  {
  public:
    // types:

    using executor_type = io_context::executor_type;
    using native_handle_type = implementation-defined; // see [socket.reqmts.native]
    using protocol_type = AcceptableProtocol;
    using endpoint_type = typename protocol_type::endpoint;
    using socket_type = typename protocol_type::socket;

    // [socket.acceptor.cons], construct / copy / destroy:

    explicit basic_socket_acceptor(io_context& ctx);
    basic_socket_acceptor(io_context& ctx, const protocol_type& protocol);
    basic_socket_acceptor(io_context& ctx, const endpoint_type& endpoint,
                          bool reuse_addr = true);
    basic_socket_acceptor(io_context& ctx, const protocol_type& protocol,
                          const native_handle_type& native_acceptor);
    basic_socket_acceptor(const basic_socket_acceptor&) = delete;
    basic_socket_acceptor(basic_socket_acceptor&& rhs);
    template<class OtherProtocol>
      basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs);

    ~basic_socket_acceptor();

    basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete;
    basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs);
    template<class OtherProtocol>
      basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs);

    // [socket.acceptor.ops], basic_socket_acceptor operations:

    executor_type get_executor() noexcept;

    native_handle_type native_handle(); // see [socket.reqmts.native]

    void open(const protocol_type& protocol = protocol_type());
    void open(const protocol_type& protocol, error_code& ec);

    void assign(const protocol_type& protocol,
                const native_handle_type& native_acceptor); // see [socket.reqmts.native]
    void assign(const protocol_type& protocol,
                const native_handle_type& native_acceptor,
                error_code& ec); // see [socket.reqmts.native]

    native_handle_type release(); // see [socket.reqmts.native]
    native_handle_type release(error_code& ec); // see [socket.reqmts.native]

    bool is_open() const noexcept;

    void close();
    void close(error_code& ec);

    void cancel();
    void cancel(error_code& ec);

    template<class SettableSocketOption>
      void set_option(const SettableSocketOption& option);
    template<class SettableSocketOption>
      void set_option(const SettableSocketOption& option, error_code& ec);

    template<class GettableSocketOption>
      void get_option(GettableSocketOption& option) const;
    template<class GettableSocketOption>
      void get_option(GettableSocketOption& option, error_code& ec) const;

    template<class IoControlCommand>
      void io_control(IoControlCommand& command);
    template<class IoControlCommand>
      void io_control(IoControlCommand& command, error_code& ec);

    void non_blocking(bool mode);
    void non_blocking(bool mode, error_code& ec);
    bool non_blocking() const;

    void native_non_blocking(bool mode);
    void native_non_blocking(bool mode, error_code& ec);
    bool native_non_blocking() const;

    void bind(const endpoint_type& endpoint);
    void bind(const endpoint_type& endpoint, error_code& ec);

    void listen(int backlog = max_listen_connections);
    void listen(int backlog, error_code& ec);

    endpoint_type local_endpoint() const;
    endpoint_type local_endpoint(error_code& ec) const;

    void enable_connection_aborted(bool mode);
    bool enable_connection_aborted() const;

    socket_type accept();
    socket_type accept(error_code& ec);
    socket_type accept(io_context& ctx);
    socket_type accept(io_context& ctx, error_code& ec);

    template<class CompletionToken>
      DEDUCED async_accept(CompletionToken&& token);
    template<class CompletionToken>
      DEDUCED async_accept(io_context& ctx, CompletionToken&& token);

    socket_type accept(endpoint_type& endpoint);
    socket_type accept(endpoint_type& endpoint, error_code& ec);
    socket_type accept(io_context& ctx, endpoint_type& endpoint);
    socket_type accept(io_context& ctx, endpoint_type& endpoint,
                       error_code& ec);

    template<class CompletionToken>
      DEDUCED async_accept(endpoint_type& endpoint,
                           CompletionToken&& token);
    template<class CompletionToken>
      DEDUCED async_accept(io_context& ctx, endpoint_type& endpoint,
                           CompletionToken&& token);

    void wait(wait_type w);
    void wait(wait_type w, error_code& ec);

    template<class CompletionToken>
      DEDUCED async_wait(wait_type w, CompletionToken&& token);

  private:
    protocol_type protocol_; // exposition only
  };

} // inline namespace v1
} // namespace net
} // namespace experimental
} // namespace std

Instances of class template basic_socket_acceptor meet the requirements of Destructible (C++ 2014 [destructible]), MoveConstructible (C++ 2014 [moveconstructible]), and MoveAssignable (C++ 2014 [moveassignable]).

When there are multiple outstanding asynchronous accept operations the order in which the incoming connections are dequeued, and the order of invocation of the completion handlers for these operations, is unspecified.

When an operation has its effects specified as if by passing the result of native_handle() to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false at the point in the effects when the POSIX function is called.

18.9.1 basic_socket_acceptor constructors [socket.acceptor.cons]

explicit basic_socket_acceptor(io_context& ctx);

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == false.

basic_socket_acceptor(io_context& ctx, const protocol_type& protocol);

Effects: Opens this acceptor as if by calling open(protocol).

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • enable_connection_aborted() == false.

  • protocol_ == protocol.

basic_socket_acceptor(io_context& ctx, const endpoint_type& endpoint, bool reuse_addr = true);

Effects: Opens and binds this acceptor as if by calling:

open(endpoint.protocol());
if (reuse_addr)
  set_option(reuse_address(true));
bind(endpoint);
listen();

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • enable_connection_aborted() == false.

  • protocol_ == endpoint.protocol().

basic_socket_acceptor(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_acceptor);

Requires: native_acceptor is a native handle to an open acceptor.

Effects: Assigns the existing native acceptor into this acceptor as if by calling assign(protocol, native_acceptor).

Postconditions:

  • get_executor() == ctx.get_executor().

  • is_open() == true.

  • non_blocking() == false.

  • enable_connection_aborted() == false.

  • protocol_ == protocol.

basic_socket_acceptor(basic_socket_acceptor&& rhs);

Effects: Move constructs an object of class basic_socket_acceptor<AcceptableProtocol> that refers to the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the constructor invocation.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the constructor invocation.

  • enable_connection_aborted() returns the same value as rhs.enable_connection_aborted() prior to the constructor invocation.

  • native_handle() returns the same value as rhs.native_handle() prior to the constructor invocation.

  • protocol_ is equal to the prior value of rhs.protocol_.

  • rhs.is_open() == false.

template<class OtherProtocol> basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: Move constructs an object of class basic_socket_acceptor<AcceptableProtocol> that refers to the state originally represented by rhs.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the constructor invocation.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the constructor invocation.

  • enable_connection_aborted() returns the same value as rhs.enable_connection_aborted() prior to the constructor invocation.

  • native_handle() returns the prior value of rhs.native_handle().

  • protocol_ is the result of converting the prior value of rhs.protocol_.

  • rhs.is_open() == false.

Remarks: This constructor shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.9.2 basic_socket_acceptor destructor [socket.acceptor.dtor]

~basic_socket_acceptor();

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIX close(native_handle()). Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true.

18.9.3 basic_socket_acceptor assignment [socket.acceptor.assign]

basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs);

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIX close(native_handle()). Then moves into *this the state originally represented by rhs. Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the assignment.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the assignment.

  • enable_connection_aborted() returns the same value as rhs.enable_connection_aborted() prior to the assignment.

  • native_handle() returns the same value as rhs.native_handle() prior to the assignment.

  • protocol_ is the same value as rhs.protocol_ prior to the assignment.

  • rhs.is_open() == false.

Returns: *this.

template<class OtherProtocol> basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs);

Requires: OtherProtocol is implicitly convertible to Protocol.

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIX close(native_handle()). Then moves into *this the state originally represented by rhs. Completion handlers for canceled operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Postconditions:

  • get_executor() == rhs.get_executor().

  • is_open() returns the same value as rhs.is_open() prior to the assignment.

  • non_blocking() returns the same value as rhs.non_blocking() prior to the assignment.

  • enable_connection_aborted() returns the same value as rhs.enable_connection_aborted() prior to the assignment.

  • native_handle() returns the same value as rhs.native_handle() prior to the assignment.

  • protocol_ is the result of converting the value of rhs.protocol_ prior to the assignment.

  • rhs.is_open() == false.

Returns: *this.

Remarks: This assignment operator shall not participate in overload resolution unless OtherProtocol is implicitly convertible to Protocol.

18.9.4 basic_socket_acceptor operations [socket.acceptor.ops]

executor_type get_executor() noexcept;

Returns: The associated executor.

native_handle_type native_handle();

Returns: The native representation of this acceptor.

void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);

Effects: Establishes the postcondition, as if by POSIX:

socket(protocol.family(), protocol.type(), protocol.protocol());

Postconditions:

  • is_open() == true.

  • non_blocking() == false.

  • enable_connection_aborted() == false.

  • protocol_ == protocol.

Error conditions:

  • socket_errc::already_open — if is_open() is true.

void assign(const protocol_type& protocol, const native_handle_type& native_acceptor); void assign(const protocol_type& protocol, const native_handle_type& native_acceptor, error_code& ec);

Requires: native_acceptor is a native handle to an open acceptor.

Effects: Assigns the native acceptor handle to this acceptor object.

Postconditions:

  • is_open() == true.

  • non_blocking() == false.

  • enable_connection_aborted() == false.

  • protocol_ == protocol.

Error conditions:

  • socket_errc::already_open — if is_open() is true.

native_handle_type release(); native_handle_type release(error_code& ec);

Requires: is_open() == true.

Effects: Cancels all outstanding asynchronous operations associated with this acceptor. Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Returns: The native representation of this acceptor.

Postconditions: is_open() == false.

Remarks: Since the native acceptor is not closed prior to returning it, the caller is responsible for closing it.

bool is_open() const noexcept;

Returns: A bool indicating whether this acceptor was opened by a previous call to open or assign.

void close(); void close(error_code& ec);

Effects: If is_open() is true, cancels all outstanding asynchronous operations associated with this acceptor, and establishes the postcondition as if by POSIX close(native_handle()). Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Postconditions: is_open() == false.

void cancel(); void cancel(error_code& ec);

Effects: Cancels all outstanding asynchronous operations associated with this acceptor. Completion handlers for canceled asynchronous operations are passed an error code ec such that ec == errc::operation_canceled yields true.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

  • errc::operation_not_supported — current conditions do not permit cancelation. The conditions under which cancelation of asynchronous operations is permitted are implementation-defined.

template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);

Effects: Sets an option on this acceptor, as if by POSIX:

setsockopt(native_handle(), option.level(protocol_), option.name(protocol_),
           option.data(protocol_), option.size(protocol_));

template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);

Effects: Gets an option from this acceptor, as if by POSIX:

socklen_t option_len = option.size(protocol_);
int result = getsockopt(native_handle(), option.level(protocol_),
                        option.name(protocol_), option.data(protocol_),
                        &option_len);
if (result == 0)
  option.resize(option_len);

template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);

Effects: Executes an I/O control command on this acceptor, as if by POSIX:

ioctl(native_handle(), command.name(), command.data());

void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);

Effects: Sets the non-blocking mode of this acceptor. The non-blocking mode determines whether subsequent synchronous socket operations ([socket.reqmts.sync]) on *this block the calling thread.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

Postconditions: non_blocking() == mode.

Note: The non-blocking mode has no effect on the behavior of asynchronous operations.  — end note ]

bool non_blocking() const;

Returns: The non-blocking mode of this acceptor.

void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);

Effects: Sets the non-blocking mode of the underlying native acceptor, as if by POSIX:

int flags = fcntl(native_handle(), F_GETFL, 0);
if (flags >= 0){
  if (mode)
    flags |= O_NONBLOCK;
  else
    flags &= ~O_NONBLOCK;
  fcntl(native_handle(), F_SETFL, flags);
}

The native non-blocking mode has no effect on the behavior of the synchronous or asynchronous operations specified in this clause.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

  • errc::invalid_argument — if mode == false and non_blocking() == true. [ Note: As the combination does not make sense.  — end note ]

bool native_non_blocking() const;

Returns: The non-blocking mode of the underlying native acceptor.

Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to native_non_blocking. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the acceptor, by calling an operating system-specific function on the result of native_handle().

void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);

Effects: Binds this acceptor to the specified local endpoint, as if by POSIX:

bind(native_handle(), endpoint.data(), endpoint.size());

void listen(int backlog = socket_base::max_listen_connections); void listen(int backlog, error_code& ec);

Effects: Marks this acceptor as ready to accept connections, as if by POSIX:

listen(native_handle(), backlog);

endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;

Effects: Determines the locally-bound endpoint associated with this acceptor, as if by POSIX:

endpoint_type endpoint;
socklen_t endpoint_len = endpoint.capacity();
int result = getsockname(native_handle(), endpoint.data(), &endpoint_len);
if (result == 0)
  endpoint.resize(endpoint_len);

Returns: On success, endpoint. Otherwise endpoint_type().

void enable_connection_aborted(bool mode);

Effects: If mode is true, subsequent synchronous or asynchronous accept operations on this acceptor are permitted to fail with error condition errc::connection_aborted. If mode is false, subsequent accept operations will not fail with errc::connection_aborted. [ Note: If mode is false, the implementation will restart the call to POSIX accept if it fails with ECONNABORTED.  — end note ]

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.

bool enable_connection_aborted() const;

Returns: Whether accept operations on this acceptor are permitted to fail with errc::connection_aborted.

socket_type accept(); socket_type accept(error_code& ec);

Returns: accept(get_executor().context(), ec).

socket_type accept(io_context& ctx); socket_type accept(io_context& ctx, error_code& ec);

Effects: Extracts a socket from the queue of pending connections of the acceptor, as if by POSIX:

native_handle_type h = accept(native_handle(), nullptr, 0);

Returns: On success, socket_type(ctx, protocol_, h). Otherwise socket_type(ctx).

template<class CompletionToken> DEDUCED async_accept(CompletionToken&& token);

Returns:

async_accept(get_executor().context(), forward<CompletionToken>(token))

template<class CompletionToken> DEDUCED async_accept(io_context& ctx, CompletionToken&& token);

Completion signature: void(error_code ec, socket_type s).

Effects: Initiates an asynchronous operation to extract a socket from the queue of pending connections of the acceptor, as if by POSIX:

native_handle_type h = accept(native_handle(), nullptr, 0);

On success, s is socket_type(ctx, protocol_, h). Otherwise, s is socket_type(ctx).

socket_type accept(endpoint_type& endpoint); socket_type accept(endpoint_type& endpoint, error_code& ec);

Returns: accept(get_executor().context(), endpoint, ec).

socket_type accept(io_context& ctx, endpoint_type& endpoint); socket_type accept(io_context& ctx, endpoint_type& endpoint, error_code& ec);

Effects: Extracts a socket from the queue of pending connections of the acceptor, as if by POSIX:

socklen_t endpoint_len = endpoint.capacity();
native_handle_type h = accept(native_handle(),
                              endpoint.data(),
                              &endpoint_len);
if (h >= 0)
  endpoint.resize(endpoint_len);

Returns: On success, socket_type(ctx, protocol_, h). Otherwise socket_type(ctx).

template<class CompletionToken> DEDUCED async_accept(endpoint_type& endpoint, CompletionToken&& token);

Returns:

async_accept(get_executor().context(), endpoint, forward<CompletionToken>(token))

template<class CompletionToken> DEDUCED async_accept(io_context& ctx, endpoint_type& endpoint, CompletionToken&& token);

Completion signature: void(error_code ec, socket_type s).

Effects: Initiates an asynchronous operation to extract a socket from the queue of pending connections of the acceptor, as if by POSIX:

socklen_t endpoint_len = endpoint.capacity();
native_handle_type h = accept(native_handle(),
                              endpoint.data(),
                              &endpoint_len);
if (h >= 0)
  endpoint.resize(endpoint_len);

On success, s is socket_type(ctx, protocol_, h). Otherwise, s is socket_type(ctx).

void wait(wait_type w); void wait(wait_type w, error_code& ec);

Effects: Waits for the acceptor to have a queued incoming connection, or to have error conditions pending, as if by POSIX poll.

template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token);

Completion signature: void(error_code ec).

Effects: Initiates an asynchronous operation to wait for the acceptor to have a queued incoming connection, or to have error conditions pending, as if by POSIX poll.

When multiple asynchronous wait operations are initiated with the same wait_type value, all outstanding operations complete when the acceptor enters the corresponding ready state. The order of invocation of the completions handlers for these operations is unspecified.

Error conditions:

  • errc::bad_file_descriptor — if is_open() is false.