Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:39

0001 //
0002 // basic_datagram_socket.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
0012 #define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <boost/asio/basic_socket.hpp>
0021 #include <boost/asio/detail/handler_type_requirements.hpp>
0022 #include <boost/asio/detail/non_const_lvalue.hpp>
0023 #include <boost/asio/detail/throw_error.hpp>
0024 #include <boost/asio/detail/type_traits.hpp>
0025 #include <boost/asio/error.hpp>
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 
0032 #if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
0033 #define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL
0034 
0035 // Forward declaration with defaulted arguments.
0036 template <typename Protocol, typename Executor = any_io_executor>
0037 class basic_datagram_socket;
0038 
0039 #endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)
0040 
0041 /// Provides datagram-oriented socket functionality.
0042 /**
0043  * The basic_datagram_socket class template provides asynchronous and blocking
0044  * datagram-oriented socket functionality.
0045  *
0046  * @par Thread Safety
0047  * @e Distinct @e objects: Safe.@n
0048  * @e Shared @e objects: Unsafe.
0049  *
0050  * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,
0051  * and @c shutdown operations are thread safe with respect to each other, if
0052  * the underlying operating system calls are also thread safe. This means that
0053  * it is permitted to perform concurrent calls to these synchronous operations
0054  * on a single socket object. Other synchronous operations, such as @c open or
0055  * @c close, are not thread safe.
0056  */
0057 template <typename Protocol, typename Executor>
0058 class basic_datagram_socket
0059   : public basic_socket<Protocol, Executor>
0060 {
0061 private:
0062   class initiate_async_send;
0063   class initiate_async_send_to;
0064   class initiate_async_receive;
0065   class initiate_async_receive_from;
0066 
0067 public:
0068   /// The type of the executor associated with the object.
0069   typedef Executor executor_type;
0070 
0071   /// Rebinds the socket type to another executor.
0072   template <typename Executor1>
0073   struct rebind_executor
0074   {
0075     /// The socket type when rebound to the specified executor.
0076     typedef basic_datagram_socket<Protocol, Executor1> other;
0077   };
0078 
0079   /// The native representation of a socket.
0080 #if defined(GENERATING_DOCUMENTATION)
0081   typedef implementation_defined native_handle_type;
0082 #else
0083   typedef typename basic_socket<Protocol,
0084     Executor>::native_handle_type native_handle_type;
0085 #endif
0086 
0087   /// The protocol type.
0088   typedef Protocol protocol_type;
0089 
0090   /// The endpoint type.
0091   typedef typename Protocol::endpoint endpoint_type;
0092 
0093   /// Construct a basic_datagram_socket without opening it.
0094   /**
0095    * This constructor creates a datagram socket without opening it. The open()
0096    * function must be called before data can be sent or received on the socket.
0097    *
0098    * @param ex The I/O executor that the socket will use, by default, to
0099    * dispatch handlers for any asynchronous operations performed on the socket.
0100    */
0101   explicit basic_datagram_socket(const executor_type& ex)
0102     : basic_socket<Protocol, Executor>(ex)
0103   {
0104   }
0105 
0106   /// Construct a basic_datagram_socket without opening it.
0107   /**
0108    * This constructor creates a datagram socket without opening it. The open()
0109    * function must be called before data can be sent or received on the socket.
0110    *
0111    * @param context An execution context which provides the I/O executor that
0112    * the socket will use, by default, to dispatch handlers for any asynchronous
0113    * operations performed on the socket.
0114    */
0115   template <typename ExecutionContext>
0116   explicit basic_datagram_socket(ExecutionContext& context,
0117       constraint_t<
0118         is_convertible<ExecutionContext&, execution_context&>::value
0119       > = 0)
0120     : basic_socket<Protocol, Executor>(context)
0121   {
0122   }
0123 
0124   /// Construct and open a basic_datagram_socket.
0125   /**
0126    * This constructor creates and opens a datagram socket.
0127    *
0128    * @param ex The I/O executor that the socket will use, by default, to
0129    * dispatch handlers for any asynchronous operations performed on the socket.
0130    *
0131    * @param protocol An object specifying protocol parameters to be used.
0132    *
0133    * @throws boost::system::system_error Thrown on failure.
0134    */
0135   basic_datagram_socket(const executor_type& ex, const protocol_type& protocol)
0136     : basic_socket<Protocol, Executor>(ex, protocol)
0137   {
0138   }
0139 
0140   /// Construct and open a basic_datagram_socket.
0141   /**
0142    * This constructor creates and opens a datagram socket.
0143    *
0144    * @param context An execution context which provides the I/O executor that
0145    * the socket will use, by default, to dispatch handlers for any asynchronous
0146    * operations performed on the socket.
0147    *
0148    * @param protocol An object specifying protocol parameters to be used.
0149    *
0150    * @throws boost::system::system_error Thrown on failure.
0151    */
0152   template <typename ExecutionContext>
0153   basic_datagram_socket(ExecutionContext& context,
0154       const protocol_type& protocol,
0155       constraint_t<
0156         is_convertible<ExecutionContext&, execution_context&>::value,
0157         defaulted_constraint
0158       > = defaulted_constraint())
0159     : basic_socket<Protocol, Executor>(context, protocol)
0160   {
0161   }
0162 
0163   /// Construct a basic_datagram_socket, opening it and binding it to the given
0164   /// local endpoint.
0165   /**
0166    * This constructor creates a datagram socket and automatically opens it bound
0167    * to the specified endpoint on the local machine. The protocol used is the
0168    * protocol associated with the given endpoint.
0169    *
0170    * @param ex The I/O executor that the socket will use, by default, to
0171    * dispatch handlers for any asynchronous operations performed on the socket.
0172    *
0173    * @param endpoint An endpoint on the local machine to which the datagram
0174    * socket will be bound.
0175    *
0176    * @throws boost::system::system_error Thrown on failure.
0177    */
0178   basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint)
0179     : basic_socket<Protocol, Executor>(ex, endpoint)
0180   {
0181   }
0182 
0183   /// Construct a basic_datagram_socket, opening it and binding it to the given
0184   /// local endpoint.
0185   /**
0186    * This constructor creates a datagram socket and automatically opens it bound
0187    * to the specified endpoint on the local machine. The protocol used is the
0188    * protocol associated with the given endpoint.
0189    *
0190    * @param context An execution context which provides the I/O executor that
0191    * the socket will use, by default, to dispatch handlers for any asynchronous
0192    * operations performed on the socket.
0193    *
0194    * @param endpoint An endpoint on the local machine to which the datagram
0195    * socket will be bound.
0196    *
0197    * @throws boost::system::system_error Thrown on failure.
0198    */
0199   template <typename ExecutionContext>
0200   basic_datagram_socket(ExecutionContext& context,
0201       const endpoint_type& endpoint,
0202       constraint_t<
0203         is_convertible<ExecutionContext&, execution_context&>::value
0204       > = 0)
0205     : basic_socket<Protocol, Executor>(context, endpoint)
0206   {
0207   }
0208 
0209   /// Construct a basic_datagram_socket on an existing native socket.
0210   /**
0211    * This constructor creates a datagram socket object to hold an existing
0212    * native socket.
0213    *
0214    * @param ex The I/O executor that the socket will use, by default, to
0215    * dispatch handlers for any asynchronous operations performed on the socket.
0216    *
0217    * @param protocol An object specifying protocol parameters to be used.
0218    *
0219    * @param native_socket The new underlying socket implementation.
0220    *
0221    * @throws boost::system::system_error Thrown on failure.
0222    */
0223   basic_datagram_socket(const executor_type& ex,
0224       const protocol_type& protocol, const native_handle_type& native_socket)
0225     : basic_socket<Protocol, Executor>(ex, protocol, native_socket)
0226   {
0227   }
0228 
0229   /// Construct a basic_datagram_socket on an existing native socket.
0230   /**
0231    * This constructor creates a datagram socket object to hold an existing
0232    * native socket.
0233    *
0234    * @param context An execution context which provides the I/O executor that
0235    * the socket will use, by default, to dispatch handlers for any asynchronous
0236    * operations performed on the socket.
0237    *
0238    * @param protocol An object specifying protocol parameters to be used.
0239    *
0240    * @param native_socket The new underlying socket implementation.
0241    *
0242    * @throws boost::system::system_error Thrown on failure.
0243    */
0244   template <typename ExecutionContext>
0245   basic_datagram_socket(ExecutionContext& context,
0246       const protocol_type& protocol, const native_handle_type& native_socket,
0247       constraint_t<
0248         is_convertible<ExecutionContext&, execution_context&>::value
0249       > = 0)
0250     : basic_socket<Protocol, Executor>(context, protocol, native_socket)
0251   {
0252   }
0253 
0254   /// Move-construct a basic_datagram_socket from another.
0255   /**
0256    * This constructor moves a datagram socket from one object to another.
0257    *
0258    * @param other The other basic_datagram_socket object from which the move
0259    * will occur.
0260    *
0261    * @note Following the move, the moved-from object is in the same state as if
0262    * constructed using the @c basic_datagram_socket(const executor_type&)
0263    * constructor.
0264    */
0265   basic_datagram_socket(basic_datagram_socket&& other) noexcept
0266     : basic_socket<Protocol, Executor>(std::move(other))
0267   {
0268   }
0269 
0270   /// Move-assign a basic_datagram_socket from another.
0271   /**
0272    * This assignment operator moves a datagram socket from one object to
0273    * another.
0274    *
0275    * @param other The other basic_datagram_socket object from which the move
0276    * will occur.
0277    *
0278    * @note Following the move, the moved-from object is in the same state as if
0279    * constructed using the @c basic_datagram_socket(const executor_type&)
0280    * constructor.
0281    */
0282   basic_datagram_socket& operator=(basic_datagram_socket&& other)
0283   {
0284     basic_socket<Protocol, Executor>::operator=(std::move(other));
0285     return *this;
0286   }
0287 
0288   /// Move-construct a basic_datagram_socket from a socket of another protocol
0289   /// type.
0290   /**
0291    * This constructor moves a datagram socket from one object to another.
0292    *
0293    * @param other The other basic_datagram_socket object from which the move
0294    * will occur.
0295    *
0296    * @note Following the move, the moved-from object is in the same state as if
0297    * constructed using the @c basic_datagram_socket(const executor_type&)
0298    * constructor.
0299    */
0300   template <typename Protocol1, typename Executor1>
0301   basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,
0302       constraint_t<
0303         is_convertible<Protocol1, Protocol>::value
0304           && is_convertible<Executor1, Executor>::value
0305       > = 0)
0306     : basic_socket<Protocol, Executor>(std::move(other))
0307   {
0308   }
0309 
0310   /// Move-assign a basic_datagram_socket from a socket of another protocol
0311   /// type.
0312   /**
0313    * This assignment operator moves a datagram socket from one object to
0314    * another.
0315    *
0316    * @param other The other basic_datagram_socket object from which the move
0317    * will occur.
0318    *
0319    * @note Following the move, the moved-from object is in the same state as if
0320    * constructed using the @c basic_datagram_socket(const executor_type&)
0321    * constructor.
0322    */
0323   template <typename Protocol1, typename Executor1>
0324   constraint_t<
0325     is_convertible<Protocol1, Protocol>::value
0326       && is_convertible<Executor1, Executor>::value,
0327     basic_datagram_socket&
0328   > operator=(basic_datagram_socket<Protocol1, Executor1>&& other)
0329   {
0330     basic_socket<Protocol, Executor>::operator=(std::move(other));
0331     return *this;
0332   }
0333 
0334   /// Destroys the socket.
0335   /**
0336    * This function destroys the socket, cancelling any outstanding asynchronous
0337    * operations associated with the socket as if by calling @c cancel.
0338    */
0339   ~basic_datagram_socket()
0340   {
0341   }
0342 
0343   /// Send some data on a connected socket.
0344   /**
0345    * This function is used to send data on the datagram socket. The function
0346    * call will block until the data has been sent successfully or an error
0347    * occurs.
0348    *
0349    * @param buffers One ore more data buffers to be sent on the socket.
0350    *
0351    * @returns The number of bytes sent.
0352    *
0353    * @throws boost::system::system_error Thrown on failure.
0354    *
0355    * @note The send operation can only be used with a connected socket. Use
0356    * the send_to function to send data on an unconnected datagram socket.
0357    *
0358    * @par Example
0359    * To send a single data buffer use the @ref buffer function as follows:
0360    * @code socket.send(boost::asio::buffer(data, size)); @endcode
0361    * See the @ref buffer documentation for information on sending multiple
0362    * buffers in one go, and how to use it with arrays, boost::array or
0363    * std::vector.
0364    */
0365   template <typename ConstBufferSequence>
0366   std::size_t send(const ConstBufferSequence& buffers)
0367   {
0368     boost::system::error_code ec;
0369     std::size_t s = this->impl_.get_service().send(
0370         this->impl_.get_implementation(), buffers, 0, ec);
0371     boost::asio::detail::throw_error(ec, "send");
0372     return s;
0373   }
0374 
0375   /// Send some data on a connected socket.
0376   /**
0377    * This function is used to send data on the datagram socket. The function
0378    * call will block until the data has been sent successfully or an error
0379    * occurs.
0380    *
0381    * @param buffers One ore more data buffers to be sent on the socket.
0382    *
0383    * @param flags Flags specifying how the send call is to be made.
0384    *
0385    * @returns The number of bytes sent.
0386    *
0387    * @throws boost::system::system_error Thrown on failure.
0388    *
0389    * @note The send operation can only be used with a connected socket. Use
0390    * the send_to function to send data on an unconnected datagram socket.
0391    */
0392   template <typename ConstBufferSequence>
0393   std::size_t send(const ConstBufferSequence& buffers,
0394       socket_base::message_flags flags)
0395   {
0396     boost::system::error_code ec;
0397     std::size_t s = this->impl_.get_service().send(
0398         this->impl_.get_implementation(), buffers, flags, ec);
0399     boost::asio::detail::throw_error(ec, "send");
0400     return s;
0401   }
0402 
0403   /// Send some data on a connected socket.
0404   /**
0405    * This function is used to send data on the datagram socket. The function
0406    * call will block until the data has been sent successfully or an error
0407    * occurs.
0408    *
0409    * @param buffers One or more data buffers to be sent on the socket.
0410    *
0411    * @param flags Flags specifying how the send call is to be made.
0412    *
0413    * @param ec Set to indicate what error occurred, if any.
0414    *
0415    * @returns The number of bytes sent.
0416    *
0417    * @note The send operation can only be used with a connected socket. Use
0418    * the send_to function to send data on an unconnected datagram socket.
0419    */
0420   template <typename ConstBufferSequence>
0421   std::size_t send(const ConstBufferSequence& buffers,
0422       socket_base::message_flags flags, boost::system::error_code& ec)
0423   {
0424     return this->impl_.get_service().send(
0425         this->impl_.get_implementation(), buffers, flags, ec);
0426   }
0427 
0428   /// Start an asynchronous send on a connected socket.
0429   /**
0430    * This function is used to asynchronously send data on the datagram socket.
0431    * It is an initiating function for an @ref asynchronous_operation, and always
0432    * returns immediately.
0433    *
0434    * @param buffers One or more data buffers to be sent on the socket. Although
0435    * the buffers object may be copied as necessary, ownership of the underlying
0436    * memory blocks is retained by the caller, which must guarantee that they
0437    * remain valid until the completion handler is called.
0438    *
0439    * @param token The @ref completion_token that will be used to produce a
0440    * completion handler, which will be called when the send completes. Potential
0441    * completion tokens include @ref use_future, @ref use_awaitable, @ref
0442    * yield_context, or a function object with the correct completion signature.
0443    * The function signature of the completion handler must be:
0444    * @code void handler(
0445    *   const boost::system::error_code& error, // Result of operation.
0446    *   std::size_t bytes_transferred // Number of bytes sent.
0447    * ); @endcode
0448    * Regardless of whether the asynchronous operation completes immediately or
0449    * not, the completion handler will not be invoked from within this function.
0450    * On immediate completion, invocation of the handler will be performed in a
0451    * manner equivalent to using boost::asio::post().
0452    *
0453    * @par Completion Signature
0454    * @code void(boost::system::error_code, std::size_t) @endcode
0455    *
0456    * @note The async_send operation can only be used with a connected socket.
0457    * Use the async_send_to function to send data on an unconnected datagram
0458    * socket.
0459    *
0460    * @par Example
0461    * To send a single data buffer use the @ref buffer function as follows:
0462    * @code
0463    * socket.async_send(boost::asio::buffer(data, size), handler);
0464    * @endcode
0465    * See the @ref buffer documentation for information on sending multiple
0466    * buffers in one go, and how to use it with arrays, boost::array or
0467    * std::vector.
0468    *
0469    * @par Per-Operation Cancellation
0470    * On POSIX or Windows operating systems, this asynchronous operation supports
0471    * cancellation for the following boost::asio::cancellation_type values:
0472    *
0473    * @li @c cancellation_type::terminal
0474    *
0475    * @li @c cancellation_type::partial
0476    *
0477    * @li @c cancellation_type::total
0478    */
0479   template <typename ConstBufferSequence,
0480       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0481         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0482   auto async_send(const ConstBufferSequence& buffers,
0483       WriteToken&& token = default_completion_token_t<executor_type>())
0484     -> decltype(
0485       async_initiate<WriteToken,
0486         void (boost::system::error_code, std::size_t)>(
0487           declval<initiate_async_send>(), token,
0488           buffers, socket_base::message_flags(0)))
0489   {
0490     return async_initiate<WriteToken,
0491       void (boost::system::error_code, std::size_t)>(
0492         initiate_async_send(this), token,
0493         buffers, socket_base::message_flags(0));
0494   }
0495 
0496   /// Start an asynchronous send on a connected socket.
0497   /**
0498    * This function is used to asynchronously send data on the datagram socket.
0499    * It is an initiating function for an @ref asynchronous_operation, and always
0500    * returns immediately.
0501    *
0502    * @param buffers One or more data buffers to be sent on the socket. Although
0503    * the buffers object may be copied as necessary, ownership of the underlying
0504    * memory blocks is retained by the caller, which must guarantee that they
0505    * remain valid until the completion handler is called.
0506    *
0507    * @param flags Flags specifying how the send call is to be made.
0508    *
0509    * @param token The @ref completion_token that will be used to produce a
0510    * completion handler, which will be called when the send completes. Potential
0511    * completion tokens include @ref use_future, @ref use_awaitable, @ref
0512    * yield_context, or a function object with the correct completion signature.
0513    * The function signature of the completion handler must be:
0514    * @code void handler(
0515    *   const boost::system::error_code& error, // Result of operation.
0516    *   std::size_t bytes_transferred // Number of bytes sent.
0517    * ); @endcode
0518    * Regardless of whether the asynchronous operation completes immediately or
0519    * not, the completion handler will not be invoked from within this function.
0520    * On immediate completion, invocation of the handler will be performed in a
0521    * manner equivalent to using boost::asio::post().
0522    *
0523    * @par Completion Signature
0524    * @code void(boost::system::error_code, std::size_t) @endcode
0525    *
0526    * @note The async_send operation can only be used with a connected socket.
0527    * Use the async_send_to function to send data on an unconnected datagram
0528    * socket.
0529    *
0530    * @par Per-Operation Cancellation
0531    * On POSIX or Windows operating systems, this asynchronous operation supports
0532    * cancellation for the following boost::asio::cancellation_type values:
0533    *
0534    * @li @c cancellation_type::terminal
0535    *
0536    * @li @c cancellation_type::partial
0537    *
0538    * @li @c cancellation_type::total
0539    */
0540   template <typename ConstBufferSequence,
0541       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0542         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0543   auto async_send(const ConstBufferSequence& buffers,
0544       socket_base::message_flags flags,
0545       WriteToken&& token = default_completion_token_t<executor_type>())
0546     -> decltype(
0547       async_initiate<WriteToken,
0548         void (boost::system::error_code, std::size_t)>(
0549           declval<initiate_async_send>(), token, buffers, flags))
0550   {
0551     return async_initiate<WriteToken,
0552       void (boost::system::error_code, std::size_t)>(
0553         initiate_async_send(this), token, buffers, flags);
0554   }
0555 
0556   /// Send a datagram to the specified endpoint.
0557   /**
0558    * This function is used to send a datagram to the specified remote endpoint.
0559    * The function call will block until the data has been sent successfully or
0560    * an error occurs.
0561    *
0562    * @param buffers One or more data buffers to be sent to the remote endpoint.
0563    *
0564    * @param destination The remote endpoint to which the data will be sent.
0565    *
0566    * @returns The number of bytes sent.
0567    *
0568    * @throws boost::system::system_error Thrown on failure.
0569    *
0570    * @par Example
0571    * To send a single data buffer use the @ref buffer function as follows:
0572    * @code
0573    * boost::asio::ip::udp::endpoint destination(
0574    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
0575    * socket.send_to(boost::asio::buffer(data, size), destination);
0576    * @endcode
0577    * See the @ref buffer documentation for information on sending multiple
0578    * buffers in one go, and how to use it with arrays, boost::array or
0579    * std::vector.
0580    */
0581   template <typename ConstBufferSequence>
0582   std::size_t send_to(const ConstBufferSequence& buffers,
0583       const endpoint_type& destination)
0584   {
0585     boost::system::error_code ec;
0586     std::size_t s = this->impl_.get_service().send_to(
0587         this->impl_.get_implementation(), buffers, destination, 0, ec);
0588     boost::asio::detail::throw_error(ec, "send_to");
0589     return s;
0590   }
0591 
0592   /// Send a datagram to the specified endpoint.
0593   /**
0594    * This function is used to send a datagram to the specified remote endpoint.
0595    * The function call will block until the data has been sent successfully or
0596    * an error occurs.
0597    *
0598    * @param buffers One or more data buffers to be sent to the remote endpoint.
0599    *
0600    * @param destination The remote endpoint to which the data will be sent.
0601    *
0602    * @param flags Flags specifying how the send call is to be made.
0603    *
0604    * @returns The number of bytes sent.
0605    *
0606    * @throws boost::system::system_error Thrown on failure.
0607    */
0608   template <typename ConstBufferSequence>
0609   std::size_t send_to(const ConstBufferSequence& buffers,
0610       const endpoint_type& destination, socket_base::message_flags flags)
0611   {
0612     boost::system::error_code ec;
0613     std::size_t s = this->impl_.get_service().send_to(
0614         this->impl_.get_implementation(), buffers, destination, flags, ec);
0615     boost::asio::detail::throw_error(ec, "send_to");
0616     return s;
0617   }
0618 
0619   /// Send a datagram to the specified endpoint.
0620   /**
0621    * This function is used to send a datagram to the specified remote endpoint.
0622    * The function call will block until the data has been sent successfully or
0623    * an error occurs.
0624    *
0625    * @param buffers One or more data buffers to be sent to the remote endpoint.
0626    *
0627    * @param destination The remote endpoint to which the data will be sent.
0628    *
0629    * @param flags Flags specifying how the send call is to be made.
0630    *
0631    * @param ec Set to indicate what error occurred, if any.
0632    *
0633    * @returns The number of bytes sent.
0634    */
0635   template <typename ConstBufferSequence>
0636   std::size_t send_to(const ConstBufferSequence& buffers,
0637       const endpoint_type& destination, socket_base::message_flags flags,
0638       boost::system::error_code& ec)
0639   {
0640     return this->impl_.get_service().send_to(this->impl_.get_implementation(),
0641         buffers, destination, flags, ec);
0642   }
0643 
0644   /// Start an asynchronous send.
0645   /**
0646    * This function is used to asynchronously send a datagram to the specified
0647    * remote endpoint. It is an initiating function for an @ref
0648    * asynchronous_operation, and always returns immediately.
0649    *
0650    * @param buffers One or more data buffers to be sent to the remote endpoint.
0651    * Although the buffers object may be copied as necessary, ownership of the
0652    * underlying memory blocks is retained by the caller, which must guarantee
0653    * that they remain valid until the completion handler is called.
0654    *
0655    * @param destination The remote endpoint to which the data will be sent.
0656    * Copies will be made of the endpoint as required.
0657    *
0658    * @param token The @ref completion_token that will be used to produce a
0659    * completion handler, which will be called when the send completes. Potential
0660    * completion tokens include @ref use_future, @ref use_awaitable, @ref
0661    * yield_context, or a function object with the correct completion signature.
0662    * The function signature of the completion handler must be:
0663    * @code void handler(
0664    *   const boost::system::error_code& error, // Result of operation.
0665    *   std::size_t bytes_transferred // Number of bytes sent.
0666    * ); @endcode
0667    * Regardless of whether the asynchronous operation completes immediately or
0668    * not, the completion handler will not be invoked from within this function.
0669    * On immediate completion, invocation of the handler will be performed in a
0670    * manner equivalent to using boost::asio::post().
0671    *
0672    * @par Completion Signature
0673    * @code void(boost::system::error_code, std::size_t) @endcode
0674    *
0675    * @par Example
0676    * To send a single data buffer use the @ref buffer function as follows:
0677    * @code
0678    * boost::asio::ip::udp::endpoint destination(
0679    *     boost::asio::ip::address::from_string("1.2.3.4"), 12345);
0680    * socket.async_send_to(
0681    *     boost::asio::buffer(data, size), destination, handler);
0682    * @endcode
0683    * See the @ref buffer documentation for information on sending multiple
0684    * buffers in one go, and how to use it with arrays, boost::array or
0685    * std::vector.
0686    *
0687    * @par Per-Operation Cancellation
0688    * On POSIX or Windows operating systems, this asynchronous operation supports
0689    * cancellation for the following boost::asio::cancellation_type values:
0690    *
0691    * @li @c cancellation_type::terminal
0692    *
0693    * @li @c cancellation_type::partial
0694    *
0695    * @li @c cancellation_type::total
0696    */
0697   template <typename ConstBufferSequence,
0698       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0699         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0700   auto async_send_to(const ConstBufferSequence& buffers,
0701       const endpoint_type& destination,
0702       WriteToken&& token = default_completion_token_t<executor_type>())
0703     -> decltype(
0704       async_initiate<WriteToken,
0705         void (boost::system::error_code, std::size_t)>(
0706           declval<initiate_async_send_to>(), token, buffers,
0707           destination, socket_base::message_flags(0)))
0708   {
0709     return async_initiate<WriteToken,
0710       void (boost::system::error_code, std::size_t)>(
0711         initiate_async_send_to(this), token, buffers,
0712         destination, socket_base::message_flags(0));
0713   }
0714 
0715   /// Start an asynchronous send.
0716   /**
0717    * This function is used to asynchronously send a datagram to the specified
0718    * remote endpoint. It is an initiating function for an @ref
0719    * asynchronous_operation, and always returns immediately.
0720    *
0721    * @param buffers One or more data buffers to be sent to the remote endpoint.
0722    * Although the buffers object may be copied as necessary, ownership of the
0723    * underlying memory blocks is retained by the caller, which must guarantee
0724    * that they remain valid until the completion handler is called.
0725    *
0726    * @param flags Flags specifying how the send call is to be made.
0727    *
0728    * @param destination The remote endpoint to which the data will be sent.
0729    * Copies will be made of the endpoint as required.
0730    *
0731    * @param token The @ref completion_token that will be used to produce a
0732    * completion handler, which will be called when the send completes. Potential
0733    * completion tokens include @ref use_future, @ref use_awaitable, @ref
0734    * yield_context, or a function object with the correct completion signature.
0735    * The function signature of the completion handler must be:
0736    * @code void handler(
0737    *   const boost::system::error_code& error, // Result of operation.
0738    *   std::size_t bytes_transferred // Number of bytes sent.
0739    * ); @endcode
0740    * Regardless of whether the asynchronous operation completes immediately or
0741    * not, the completion handler will not be invoked from within this function.
0742    * On immediate completion, invocation of the handler will be performed in a
0743    * manner equivalent to using boost::asio::post().
0744    *
0745    * @par Completion Signature
0746    * @code void(boost::system::error_code, std::size_t) @endcode
0747    *
0748    * @par Per-Operation Cancellation
0749    * On POSIX or Windows operating systems, this asynchronous operation supports
0750    * cancellation for the following boost::asio::cancellation_type values:
0751    *
0752    * @li @c cancellation_type::terminal
0753    *
0754    * @li @c cancellation_type::partial
0755    *
0756    * @li @c cancellation_type::total
0757    */
0758   template <typename ConstBufferSequence,
0759       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0760         std::size_t)) WriteToken = default_completion_token_t<executor_type>>
0761   auto async_send_to(const ConstBufferSequence& buffers,
0762       const endpoint_type& destination, socket_base::message_flags flags,
0763       WriteToken&& token = default_completion_token_t<executor_type>())
0764     -> decltype(
0765       async_initiate<WriteToken,
0766         void (boost::system::error_code, std::size_t)>(
0767           declval<initiate_async_send_to>(), token,
0768           buffers, destination, flags))
0769   {
0770     return async_initiate<WriteToken,
0771       void (boost::system::error_code, std::size_t)>(
0772         initiate_async_send_to(this), token,
0773         buffers, destination, flags);
0774   }
0775 
0776   /// Receive some data on a connected socket.
0777   /**
0778    * This function is used to receive data on the datagram socket. The function
0779    * call will block until data has been received successfully or an error
0780    * occurs.
0781    *
0782    * @param buffers One or more buffers into which the data will be received.
0783    *
0784    * @returns The number of bytes received.
0785    *
0786    * @throws boost::system::system_error Thrown on failure.
0787    *
0788    * @note The receive operation can only be used with a connected socket. Use
0789    * the receive_from function to receive data on an unconnected datagram
0790    * socket.
0791    *
0792    * @par Example
0793    * To receive into a single data buffer use the @ref buffer function as
0794    * follows:
0795    * @code socket.receive(boost::asio::buffer(data, size)); @endcode
0796    * See the @ref buffer documentation for information on receiving into
0797    * multiple buffers in one go, and how to use it with arrays, boost::array or
0798    * std::vector.
0799    */
0800   template <typename MutableBufferSequence>
0801   std::size_t receive(const MutableBufferSequence& buffers)
0802   {
0803     boost::system::error_code ec;
0804     std::size_t s = this->impl_.get_service().receive(
0805         this->impl_.get_implementation(), buffers, 0, ec);
0806     boost::asio::detail::throw_error(ec, "receive");
0807     return s;
0808   }
0809 
0810   /// Receive some data on a connected socket.
0811   /**
0812    * This function is used to receive data on the datagram socket. The function
0813    * call will block until data has been received successfully or an error
0814    * occurs.
0815    *
0816    * @param buffers One or more buffers into which the data will be received.
0817    *
0818    * @param flags Flags specifying how the receive call is to be made.
0819    *
0820    * @returns The number of bytes received.
0821    *
0822    * @throws boost::system::system_error Thrown on failure.
0823    *
0824    * @note The receive operation can only be used with a connected socket. Use
0825    * the receive_from function to receive data on an unconnected datagram
0826    * socket.
0827    */
0828   template <typename MutableBufferSequence>
0829   std::size_t receive(const MutableBufferSequence& buffers,
0830       socket_base::message_flags flags)
0831   {
0832     boost::system::error_code ec;
0833     std::size_t s = this->impl_.get_service().receive(
0834         this->impl_.get_implementation(), buffers, flags, ec);
0835     boost::asio::detail::throw_error(ec, "receive");
0836     return s;
0837   }
0838 
0839   /// Receive some data on a connected socket.
0840   /**
0841    * This function is used to receive data on the datagram socket. The function
0842    * call will block until data has been received successfully or an error
0843    * occurs.
0844    *
0845    * @param buffers One or more buffers into which the data will be received.
0846    *
0847    * @param flags Flags specifying how the receive call is to be made.
0848    *
0849    * @param ec Set to indicate what error occurred, if any.
0850    *
0851    * @returns The number of bytes received.
0852    *
0853    * @note The receive operation can only be used with a connected socket. Use
0854    * the receive_from function to receive data on an unconnected datagram
0855    * socket.
0856    */
0857   template <typename MutableBufferSequence>
0858   std::size_t receive(const MutableBufferSequence& buffers,
0859       socket_base::message_flags flags, boost::system::error_code& ec)
0860   {
0861     return this->impl_.get_service().receive(
0862         this->impl_.get_implementation(), buffers, flags, ec);
0863   }
0864 
0865   /// Start an asynchronous receive on a connected socket.
0866   /**
0867    * This function is used to asynchronously receive data from the datagram
0868    * socket. It is an initiating function for an @ref asynchronous_operation,
0869    * and always returns immediately.
0870    *
0871    * @param buffers One or more buffers into which the data will be received.
0872    * Although the buffers object may be copied as necessary, ownership of the
0873    * underlying memory blocks is retained by the caller, which must guarantee
0874    * that they remain valid until the completion handler is called.
0875    *
0876    * @param token The @ref completion_token that will be used to produce a
0877    * completion handler, which will be called when the receive completes.
0878    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0879    * @ref yield_context, or a function object with the correct completion
0880    * signature. The function signature of the completion handler must be:
0881    * @code void handler(
0882    *   const boost::system::error_code& error, // Result of operation.
0883    *   std::size_t bytes_transferred // Number of bytes received.
0884    * ); @endcode
0885    * Regardless of whether the asynchronous operation completes immediately or
0886    * not, the completion handler will not be invoked from within this function.
0887    * On immediate completion, invocation of the handler will be performed in a
0888    * manner equivalent to using boost::asio::post().
0889    *
0890    * @par Completion Signature
0891    * @code void(boost::system::error_code, std::size_t) @endcode
0892    *
0893    * @note The async_receive operation can only be used with a connected socket.
0894    * Use the async_receive_from function to receive data on an unconnected
0895    * datagram socket.
0896    *
0897    * @par Example
0898    * To receive into a single data buffer use the @ref buffer function as
0899    * follows:
0900    * @code
0901    * socket.async_receive(boost::asio::buffer(data, size), handler);
0902    * @endcode
0903    * See the @ref buffer documentation for information on receiving into
0904    * multiple buffers in one go, and how to use it with arrays, boost::array or
0905    * std::vector.
0906    *
0907    * @par Per-Operation Cancellation
0908    * On POSIX or Windows operating systems, this asynchronous operation supports
0909    * cancellation for the following boost::asio::cancellation_type values:
0910    *
0911    * @li @c cancellation_type::terminal
0912    *
0913    * @li @c cancellation_type::partial
0914    *
0915    * @li @c cancellation_type::total
0916    */
0917   template <typename MutableBufferSequence,
0918       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0919         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0920   auto async_receive(const MutableBufferSequence& buffers,
0921       ReadToken&& token = default_completion_token_t<executor_type>())
0922     -> decltype(
0923       async_initiate<ReadToken,
0924         void (boost::system::error_code, std::size_t)>(
0925           declval<initiate_async_receive>(), token,
0926           buffers, socket_base::message_flags(0)))
0927   {
0928     return async_initiate<ReadToken,
0929       void (boost::system::error_code, std::size_t)>(
0930         initiate_async_receive(this), token,
0931         buffers, socket_base::message_flags(0));
0932   }
0933 
0934   /// Start an asynchronous receive on a connected socket.
0935   /**
0936    * This function is used to asynchronously receive data from the datagram
0937    * socket. It is an initiating function for an @ref asynchronous_operation,
0938    * and always returns immediately.
0939    *
0940    * @param buffers One or more buffers into which the data will be received.
0941    * Although the buffers object may be copied as necessary, ownership of the
0942    * underlying memory blocks is retained by the caller, which must guarantee
0943    * that they remain valid until the completion handler is called.
0944    *
0945    * @param flags Flags specifying how the receive call is to be made.
0946    *
0947    * @param token The @ref completion_token that will be used to produce a
0948    * completion handler, which will be called when the receive completes.
0949    * Potential completion tokens include @ref use_future, @ref use_awaitable,
0950    * @ref yield_context, or a function object with the correct completion
0951    * signature. The function signature of the completion handler must be:
0952    * @code void handler(
0953    *   const boost::system::error_code& error, // Result of operation.
0954    *   std::size_t bytes_transferred // Number of bytes received.
0955    * ); @endcode
0956    * Regardless of whether the asynchronous operation completes immediately or
0957    * not, the completion handler will not be invoked from within this function.
0958    * On immediate completion, invocation of the handler will be performed in a
0959    * manner equivalent to using boost::asio::post().
0960    *
0961    * @par Completion Signature
0962    * @code void(boost::system::error_code, std::size_t) @endcode
0963    *
0964    * @note The async_receive operation can only be used with a connected socket.
0965    * Use the async_receive_from function to receive data on an unconnected
0966    * datagram socket.
0967    *
0968    * @par Per-Operation Cancellation
0969    * On POSIX or Windows operating systems, this asynchronous operation supports
0970    * cancellation for the following boost::asio::cancellation_type values:
0971    *
0972    * @li @c cancellation_type::terminal
0973    *
0974    * @li @c cancellation_type::partial
0975    *
0976    * @li @c cancellation_type::total
0977    */
0978   template <typename MutableBufferSequence,
0979       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0980         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
0981   auto async_receive(const MutableBufferSequence& buffers,
0982       socket_base::message_flags flags,
0983       ReadToken&& token = default_completion_token_t<executor_type>())
0984     -> decltype(
0985       async_initiate<ReadToken,
0986         void (boost::system::error_code, std::size_t)>(
0987           declval<initiate_async_receive>(), token, buffers, flags))
0988   {
0989     return async_initiate<ReadToken,
0990       void (boost::system::error_code, std::size_t)>(
0991         initiate_async_receive(this), token, buffers, flags);
0992   }
0993 
0994   /// Receive a datagram with the endpoint of the sender.
0995   /**
0996    * This function is used to receive a datagram. The function call will block
0997    * until data has been received successfully or an error occurs.
0998    *
0999    * @param buffers One or more buffers into which the data will be received.
1000    *
1001    * @param sender_endpoint An endpoint object that receives the endpoint of
1002    * the remote sender of the datagram.
1003    *
1004    * @returns The number of bytes received.
1005    *
1006    * @throws boost::system::system_error Thrown on failure.
1007    *
1008    * @par Example
1009    * To receive into a single data buffer use the @ref buffer function as
1010    * follows:
1011    * @code
1012    * boost::asio::ip::udp::endpoint sender_endpoint;
1013    * socket.receive_from(
1014    *     boost::asio::buffer(data, size), sender_endpoint);
1015    * @endcode
1016    * See the @ref buffer documentation for information on receiving into
1017    * multiple buffers in one go, and how to use it with arrays, boost::array or
1018    * std::vector.
1019    */
1020   template <typename MutableBufferSequence>
1021   std::size_t receive_from(const MutableBufferSequence& buffers,
1022       endpoint_type& sender_endpoint)
1023   {
1024     boost::system::error_code ec;
1025     std::size_t s = this->impl_.get_service().receive_from(
1026         this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);
1027     boost::asio::detail::throw_error(ec, "receive_from");
1028     return s;
1029   }
1030   
1031   /// Receive a datagram with the endpoint of the sender.
1032   /**
1033    * This function is used to receive a datagram. The function call will block
1034    * until data has been received successfully or an error occurs.
1035    *
1036    * @param buffers One or more buffers into which the data will be received.
1037    *
1038    * @param sender_endpoint An endpoint object that receives the endpoint of
1039    * the remote sender of the datagram.
1040    *
1041    * @param flags Flags specifying how the receive call is to be made.
1042    *
1043    * @returns The number of bytes received.
1044    *
1045    * @throws boost::system::system_error Thrown on failure.
1046    */
1047   template <typename MutableBufferSequence>
1048   std::size_t receive_from(const MutableBufferSequence& buffers,
1049       endpoint_type& sender_endpoint, socket_base::message_flags flags)
1050   {
1051     boost::system::error_code ec;
1052     std::size_t s = this->impl_.get_service().receive_from(
1053         this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
1054     boost::asio::detail::throw_error(ec, "receive_from");
1055     return s;
1056   }
1057   
1058   /// Receive a datagram with the endpoint of the sender.
1059   /**
1060    * This function is used to receive a datagram. The function call will block
1061    * until data has been received successfully or an error occurs.
1062    *
1063    * @param buffers One or more buffers into which the data will be received.
1064    *
1065    * @param sender_endpoint An endpoint object that receives the endpoint of
1066    * the remote sender of the datagram.
1067    *
1068    * @param flags Flags specifying how the receive call is to be made.
1069    *
1070    * @param ec Set to indicate what error occurred, if any.
1071    *
1072    * @returns The number of bytes received.
1073    */
1074   template <typename MutableBufferSequence>
1075   std::size_t receive_from(const MutableBufferSequence& buffers,
1076       endpoint_type& sender_endpoint, socket_base::message_flags flags,
1077       boost::system::error_code& ec)
1078   {
1079     return this->impl_.get_service().receive_from(
1080         this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
1081   }
1082 
1083   /// Start an asynchronous receive.
1084   /**
1085    * This function is used to asynchronously receive a datagram. It is an
1086    * initiating function for an @ref asynchronous_operation, and always returns
1087    * immediately.
1088    *
1089    * @param buffers One or more buffers into which the data will be received.
1090    * Although the buffers object may be copied as necessary, ownership of the
1091    * underlying memory blocks is retained by the caller, which must guarantee
1092    * that they remain valid until the completion handler is called.
1093    *
1094    * @param sender_endpoint An endpoint object that receives the endpoint of
1095    * the remote sender of the datagram. Ownership of the sender_endpoint object
1096    * is retained by the caller, which must guarantee that it is valid until the
1097    * completion handler is called.
1098    *
1099    * @param token The @ref completion_token that will be used to produce a
1100    * completion handler, which will be called when the receive completes.
1101    * Potential completion tokens include @ref use_future, @ref use_awaitable,
1102    * @ref yield_context, or a function object with the correct completion
1103    * signature. The function signature of the completion handler must be:
1104    * @code void handler(
1105    *   const boost::system::error_code& error, // Result of operation.
1106    *   std::size_t bytes_transferred // Number of bytes received.
1107    * ); @endcode
1108    * Regardless of whether the asynchronous operation completes immediately or
1109    * not, the completion handler will not be invoked from within this function.
1110    * On immediate completion, invocation of the handler will be performed in a
1111    * manner equivalent to using boost::asio::post().
1112    *
1113    * @par Completion Signature
1114    * @code void(boost::system::error_code, std::size_t) @endcode
1115    *
1116    * @par Example
1117    * To receive into a single data buffer use the @ref buffer function as
1118    * follows:
1119    * @code socket.async_receive_from(
1120    *     boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
1121    * See the @ref buffer documentation for information on receiving into
1122    * multiple buffers in one go, and how to use it with arrays, boost::array or
1123    * std::vector.
1124    *
1125    * @par Per-Operation Cancellation
1126    * On POSIX or Windows operating systems, this asynchronous operation supports
1127    * cancellation for the following boost::asio::cancellation_type values:
1128    *
1129    * @li @c cancellation_type::terminal
1130    *
1131    * @li @c cancellation_type::partial
1132    *
1133    * @li @c cancellation_type::total
1134    */
1135   template <typename MutableBufferSequence,
1136       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1137         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
1138   auto async_receive_from(const MutableBufferSequence& buffers,
1139       endpoint_type& sender_endpoint,
1140       ReadToken&& token = default_completion_token_t<executor_type>())
1141     -> decltype(
1142       async_initiate<ReadToken,
1143         void (boost::system::error_code, std::size_t)>(
1144           declval<initiate_async_receive_from>(), token, buffers,
1145           &sender_endpoint, socket_base::message_flags(0)))
1146   {
1147     return async_initiate<ReadToken,
1148       void (boost::system::error_code, std::size_t)>(
1149         initiate_async_receive_from(this), token, buffers,
1150         &sender_endpoint, socket_base::message_flags(0));
1151   }
1152 
1153   /// Start an asynchronous receive.
1154   /**
1155    * This function is used to asynchronously receive a datagram. It is an
1156    * initiating function for an @ref asynchronous_operation, and always returns
1157    * immediately.
1158    *
1159    * @param buffers One or more buffers into which the data will be received.
1160    * Although the buffers object may be copied as necessary, ownership of the
1161    * underlying memory blocks is retained by the caller, which must guarantee
1162    * that they remain valid until the completion handler is called.
1163    *
1164    * @param sender_endpoint An endpoint object that receives the endpoint of
1165    * the remote sender of the datagram. Ownership of the sender_endpoint object
1166    * is retained by the caller, which must guarantee that it is valid until the
1167    * completion handler is called.
1168    *
1169    * @param flags Flags specifying how the receive call is to be made.
1170    *
1171    * @param token The @ref completion_token that will be used to produce a
1172    * completion handler, which will be called when the receive completes.
1173    * Potential completion tokens include @ref use_future, @ref use_awaitable,
1174    * @ref yield_context, or a function object with the correct completion
1175    * signature. The function signature of the completion handler must be:
1176    * @code void handler(
1177    *   const boost::system::error_code& error, // Result of operation.
1178    *   std::size_t bytes_transferred // Number of bytes received.
1179    * ); @endcode
1180    * Regardless of whether the asynchronous operation completes immediately or
1181    * not, the completion handler will not be invoked from within this function.
1182    * On immediate completion, invocation of the handler will be performed in a
1183    * manner equivalent to using boost::asio::post().
1184    *
1185    * @par Completion Signature
1186    * @code void(boost::system::error_code, std::size_t) @endcode
1187    *
1188    * @par Per-Operation Cancellation
1189    * On POSIX or Windows operating systems, this asynchronous operation supports
1190    * cancellation for the following boost::asio::cancellation_type values:
1191    *
1192    * @li @c cancellation_type::terminal
1193    *
1194    * @li @c cancellation_type::partial
1195    *
1196    * @li @c cancellation_type::total
1197    */
1198   template <typename MutableBufferSequence,
1199       BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
1200         std::size_t)) ReadToken = default_completion_token_t<executor_type>>
1201   auto async_receive_from(const MutableBufferSequence& buffers,
1202       endpoint_type& sender_endpoint, socket_base::message_flags flags,
1203       ReadToken&& token = default_completion_token_t<executor_type>())
1204     -> decltype(
1205       async_initiate<ReadToken,
1206         void (boost::system::error_code, std::size_t)>(
1207           declval<initiate_async_receive_from>(), token,
1208           buffers, &sender_endpoint, flags))
1209   {
1210     return async_initiate<ReadToken,
1211       void (boost::system::error_code, std::size_t)>(
1212         initiate_async_receive_from(this), token,
1213         buffers, &sender_endpoint, flags);
1214   }
1215 
1216 private:
1217   // Disallow copying and assignment.
1218   basic_datagram_socket(const basic_datagram_socket&) = delete;
1219   basic_datagram_socket& operator=(
1220       const basic_datagram_socket&) = delete;
1221 
1222   class initiate_async_send
1223   { 
1224   public:
1225     typedef Executor executor_type;
1226 
1227     explicit initiate_async_send(basic_datagram_socket* self)
1228       : self_(self)
1229     {
1230     }
1231 
1232     const executor_type& get_executor() const noexcept
1233     {
1234       return self_->get_executor();
1235     }
1236 
1237     template <typename WriteHandler, typename ConstBufferSequence>
1238     void operator()(WriteHandler&& handler,
1239         const ConstBufferSequence& buffers,
1240         socket_base::message_flags flags) const
1241     {
1242       // If you get an error on the following line it means that your handler
1243       // does not meet the documented type requirements for a WriteHandler.
1244       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
1245 
1246       detail::non_const_lvalue<WriteHandler> handler2(handler);
1247       self_->impl_.get_service().async_send(
1248           self_->impl_.get_implementation(), buffers, flags,
1249           handler2.value, self_->impl_.get_executor());
1250     }
1251 
1252   private:
1253     basic_datagram_socket* self_;
1254   };
1255 
1256   class initiate_async_send_to
1257   {
1258   public:
1259     typedef Executor executor_type;
1260 
1261     explicit initiate_async_send_to(basic_datagram_socket* self)
1262       : self_(self)
1263     {
1264     }
1265 
1266     const executor_type& get_executor() const noexcept
1267     {
1268       return self_->get_executor();
1269     }
1270 
1271     template <typename WriteHandler, typename ConstBufferSequence>
1272     void operator()(WriteHandler&& handler,
1273         const ConstBufferSequence& buffers, const endpoint_type& destination,
1274         socket_base::message_flags flags) const
1275     {
1276       // If you get an error on the following line it means that your handler
1277       // does not meet the documented type requirements for a WriteHandler.
1278       BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
1279 
1280       detail::non_const_lvalue<WriteHandler> handler2(handler);
1281       self_->impl_.get_service().async_send_to(
1282           self_->impl_.get_implementation(), buffers, destination,
1283           flags, handler2.value, self_->impl_.get_executor());
1284     }
1285 
1286   private:
1287     basic_datagram_socket* self_;
1288   };
1289 
1290   class initiate_async_receive
1291   {
1292   public:
1293     typedef Executor executor_type;
1294 
1295     explicit initiate_async_receive(basic_datagram_socket* self)
1296       : self_(self)
1297     {
1298     }
1299 
1300     const executor_type& get_executor() const noexcept
1301     {
1302       return self_->get_executor();
1303     }
1304 
1305     template <typename ReadHandler, typename MutableBufferSequence>
1306     void operator()(ReadHandler&& handler,
1307         const MutableBufferSequence& buffers,
1308         socket_base::message_flags flags) const
1309     {
1310       // If you get an error on the following line it means that your handler
1311       // does not meet the documented type requirements for a ReadHandler.
1312       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1313 
1314       detail::non_const_lvalue<ReadHandler> handler2(handler);
1315       self_->impl_.get_service().async_receive(
1316           self_->impl_.get_implementation(), buffers, flags,
1317           handler2.value, self_->impl_.get_executor());
1318     }
1319 
1320   private:
1321     basic_datagram_socket* self_;
1322   };
1323 
1324   class initiate_async_receive_from
1325   {
1326   public:
1327     typedef Executor executor_type;
1328 
1329     explicit initiate_async_receive_from(basic_datagram_socket* self)
1330       : self_(self)
1331     {
1332     }
1333 
1334     const executor_type& get_executor() const noexcept
1335     {
1336       return self_->get_executor();
1337     }
1338 
1339     template <typename ReadHandler, typename MutableBufferSequence>
1340     void operator()(ReadHandler&& handler,
1341         const MutableBufferSequence& buffers, endpoint_type* sender_endpoint,
1342         socket_base::message_flags flags) const
1343     {
1344       // If you get an error on the following line it means that your handler
1345       // does not meet the documented type requirements for a ReadHandler.
1346       BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
1347 
1348       detail::non_const_lvalue<ReadHandler> handler2(handler);
1349       self_->impl_.get_service().async_receive_from(
1350           self_->impl_.get_implementation(), buffers, *sender_endpoint,
1351           flags, handler2.value, self_->impl_.get_executor());
1352     }
1353 
1354   private:
1355     basic_datagram_socket* self_;
1356   };
1357 };
1358 
1359 } // namespace asio
1360 } // namespace boost
1361 
1362 #include <boost/asio/detail/pop_options.hpp>
1363 
1364 #endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP