18 Sockets [socket]

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)).