1 // 2 // basic_datagram_socket.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_BASIC_DATAGRAM_SOCKET_HPP 12 #define ASIO_BASIC_DATAGRAM_SOCKET_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include "asio/detail/config.hpp" 19 #include <cstddef> 20 #include "asio/basic_socket.hpp" 21 #include "asio/detail/handler_type_requirements.hpp" 22 #include "asio/detail/throw_error.hpp" 23 #include "asio/detail/type_traits.hpp" 24 #include "asio/error.hpp" 25 26 #if defined(ASIO_ENABLE_OLD_SERVICES) 27 # include "asio/datagram_socket_service.hpp" 28 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 29 30 #include "asio/detail/push_options.hpp" 31 32 namespace asio { 33 34 /// Provides datagram-oriented socket functionality. 35 /** 36 * The basic_datagram_socket class template provides asynchronous and blocking 37 * datagram-oriented socket functionality. 38 * 39 * @par Thread Safety 40 * @e Distinct @e objects: Safe.@n 41 * @e Shared @e objects: Unsafe. 42 */ 43 template <typename Protocol 44 ASIO_SVC_TPARAM_DEF1(= datagram_socket_service<Protocol>)> 45 class basic_datagram_socket 46 : public basic_socket<Protocol ASIO_SVC_TARG> 47 { 48 public: 49 /// The native representation of a socket. 50 #if defined(GENERATING_DOCUMENTATION) 51 typedef implementation_defined native_handle_type; 52 #else 53 typedef typename basic_socket< 54 Protocol ASIO_SVC_TARG>::native_handle_type native_handle_type; 55 #endif 56 57 /// The protocol type. 58 typedef Protocol protocol_type; 59 60 /// The endpoint type. 61 typedef typename Protocol::endpoint endpoint_type; 62 63 /// Construct a basic_datagram_socket without opening it. 64 /** 65 * This constructor creates a datagram socket without opening it. The open() 66 * function must be called before data can be sent or received on the socket. 67 * 68 * @param io_context The io_context object that the datagram socket will use 69 * to dispatch handlers for any asynchronous operations performed on the 70 * socket. 71 */ basic_datagram_socket(asio::io_context & io_context)72 explicit basic_datagram_socket(asio::io_context& io_context) 73 : basic_socket<Protocol ASIO_SVC_TARG>(io_context) 74 { 75 } 76 77 /// Construct and open a basic_datagram_socket. 78 /** 79 * This constructor creates and opens a datagram socket. 80 * 81 * @param io_context The io_context object that the datagram socket will use 82 * to dispatch handlers for any asynchronous operations performed on the 83 * socket. 84 * 85 * @param protocol An object specifying protocol parameters to be used. 86 * 87 * @throws asio::system_error Thrown on failure. 88 */ basic_datagram_socket(asio::io_context & io_context,const protocol_type & protocol)89 basic_datagram_socket(asio::io_context& io_context, 90 const protocol_type& protocol) 91 : basic_socket<Protocol ASIO_SVC_TARG>(io_context, protocol) 92 { 93 } 94 95 /// Construct a basic_datagram_socket, opening it and binding it to the given 96 /// local endpoint. 97 /** 98 * This constructor creates a datagram socket and automatically opens it bound 99 * to the specified endpoint on the local machine. The protocol used is the 100 * protocol associated with the given endpoint. 101 * 102 * @param io_context The io_context object that the datagram socket will use 103 * to dispatch handlers for any asynchronous operations performed on the 104 * socket. 105 * 106 * @param endpoint An endpoint on the local machine to which the datagram 107 * socket will be bound. 108 * 109 * @throws asio::system_error Thrown on failure. 110 */ basic_datagram_socket(asio::io_context & io_context,const endpoint_type & endpoint)111 basic_datagram_socket(asio::io_context& io_context, 112 const endpoint_type& endpoint) 113 : basic_socket<Protocol ASIO_SVC_TARG>(io_context, endpoint) 114 { 115 } 116 117 /// Construct a basic_datagram_socket on an existing native socket. 118 /** 119 * This constructor creates a datagram socket object to hold an existing 120 * native socket. 121 * 122 * @param io_context The io_context object that the datagram socket will use 123 * to dispatch handlers for any asynchronous operations performed on the 124 * socket. 125 * 126 * @param protocol An object specifying protocol parameters to be used. 127 * 128 * @param native_socket The new underlying socket implementation. 129 * 130 * @throws asio::system_error Thrown on failure. 131 */ basic_datagram_socket(asio::io_context & io_context,const protocol_type & protocol,const native_handle_type & native_socket)132 basic_datagram_socket(asio::io_context& io_context, 133 const protocol_type& protocol, const native_handle_type& native_socket) 134 : basic_socket<Protocol ASIO_SVC_TARG>( 135 io_context, protocol, native_socket) 136 { 137 } 138 139 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 140 /// Move-construct a basic_datagram_socket from another. 141 /** 142 * This constructor moves a datagram socket from one object to another. 143 * 144 * @param other The other basic_datagram_socket object from which the move 145 * will occur. 146 * 147 * @note Following the move, the moved-from object is in the same state as if 148 * constructed using the @c basic_datagram_socket(io_context&) constructor. 149 */ basic_datagram_socket(basic_datagram_socket && other)150 basic_datagram_socket(basic_datagram_socket&& other) 151 : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other)) 152 { 153 } 154 155 /// Move-assign a basic_datagram_socket from another. 156 /** 157 * This assignment operator moves a datagram socket from one object to 158 * another. 159 * 160 * @param other The other basic_datagram_socket object from which the move 161 * will occur. 162 * 163 * @note Following the move, the moved-from object is in the same state as if 164 * constructed using the @c basic_datagram_socket(io_context&) constructor. 165 */ operator =(basic_datagram_socket && other)166 basic_datagram_socket& operator=(basic_datagram_socket&& other) 167 { 168 basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other)); 169 return *this; 170 } 171 172 /// Move-construct a basic_datagram_socket from a socket of another protocol 173 /// type. 174 /** 175 * This constructor moves a datagram socket from one object to another. 176 * 177 * @param other The other basic_datagram_socket object from which the move 178 * will occur. 179 * 180 * @note Following the move, the moved-from object is in the same state as if 181 * constructed using the @c basic_datagram_socket(io_context&) constructor. 182 */ 183 template <typename Protocol1 ASIO_SVC_TPARAM1> basic_datagram_socket(basic_datagram_socket<Protocol1 ASIO_SVC_TARG1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)184 basic_datagram_socket( 185 basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other, 186 typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) 187 : basic_socket<Protocol ASIO_SVC_TARG>(std::move(other)) 188 { 189 } 190 191 /// Move-assign a basic_datagram_socket from a socket of another protocol 192 /// type. 193 /** 194 * This assignment operator moves a datagram socket from one object to 195 * another. 196 * 197 * @param other The other basic_datagram_socket object from which the move 198 * will occur. 199 * 200 * @note Following the move, the moved-from object is in the same state as if 201 * constructed using the @c basic_datagram_socket(io_context&) constructor. 202 */ 203 template <typename Protocol1 ASIO_SVC_TPARAM1> 204 typename enable_if<is_convertible<Protocol1, Protocol>::value, operator =(basic_datagram_socket<Protocol1 ASIO_SVC_TARG1> && other)205 basic_datagram_socket>::type& operator=( 206 basic_datagram_socket<Protocol1 ASIO_SVC_TARG1>&& other) 207 { 208 basic_socket<Protocol ASIO_SVC_TARG>::operator=(std::move(other)); 209 return *this; 210 } 211 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 212 213 /// Destroys the socket. 214 /** 215 * This function destroys the socket, cancelling any outstanding asynchronous 216 * operations associated with the socket as if by calling @c cancel. 217 */ ~basic_datagram_socket()218 ~basic_datagram_socket() 219 { 220 } 221 222 /// Send some data on a connected socket. 223 /** 224 * This function is used to send data on the datagram socket. The function 225 * call will block until the data has been sent successfully or an error 226 * occurs. 227 * 228 * @param buffers One ore more data buffers to be sent on the socket. 229 * 230 * @returns The number of bytes sent. 231 * 232 * @throws asio::system_error Thrown on failure. 233 * 234 * @note The send operation can only be used with a connected socket. Use 235 * the send_to function to send data on an unconnected datagram socket. 236 * 237 * @par Example 238 * To send a single data buffer use the @ref buffer function as follows: 239 * @code socket.send(asio::buffer(data, size)); @endcode 240 * See the @ref buffer documentation for information on sending multiple 241 * buffers in one go, and how to use it with arrays, boost::array or 242 * std::vector. 243 */ 244 template <typename ConstBufferSequence> send(const ConstBufferSequence & buffers)245 std::size_t send(const ConstBufferSequence& buffers) 246 { 247 asio::error_code ec; 248 std::size_t s = this->get_service().send( 249 this->get_implementation(), buffers, 0, ec); 250 asio::detail::throw_error(ec, "send"); 251 return s; 252 } 253 254 /// Send some data on a connected socket. 255 /** 256 * This function is used to send data on the datagram socket. The function 257 * call will block until the data has been sent successfully or an error 258 * occurs. 259 * 260 * @param buffers One ore more data buffers to be sent on the socket. 261 * 262 * @param flags Flags specifying how the send call is to be made. 263 * 264 * @returns The number of bytes sent. 265 * 266 * @throws asio::system_error Thrown on failure. 267 * 268 * @note The send operation can only be used with a connected socket. Use 269 * the send_to function to send data on an unconnected datagram socket. 270 */ 271 template <typename ConstBufferSequence> send(const ConstBufferSequence & buffers,socket_base::message_flags flags)272 std::size_t send(const ConstBufferSequence& buffers, 273 socket_base::message_flags flags) 274 { 275 asio::error_code ec; 276 std::size_t s = this->get_service().send( 277 this->get_implementation(), buffers, flags, ec); 278 asio::detail::throw_error(ec, "send"); 279 return s; 280 } 281 282 /// Send some data on a connected socket. 283 /** 284 * This function is used to send data on the datagram socket. The function 285 * call will block until the data has been sent successfully or an error 286 * occurs. 287 * 288 * @param buffers One or more data buffers to be sent on the socket. 289 * 290 * @param flags Flags specifying how the send call is to be made. 291 * 292 * @param ec Set to indicate what error occurred, if any. 293 * 294 * @returns The number of bytes sent. 295 * 296 * @note The send operation can only be used with a connected socket. Use 297 * the send_to function to send data on an unconnected datagram socket. 298 */ 299 template <typename ConstBufferSequence> send(const ConstBufferSequence & buffers,socket_base::message_flags flags,asio::error_code & ec)300 std::size_t send(const ConstBufferSequence& buffers, 301 socket_base::message_flags flags, asio::error_code& ec) 302 { 303 return this->get_service().send( 304 this->get_implementation(), buffers, flags, ec); 305 } 306 307 /// Start an asynchronous send on a connected socket. 308 /** 309 * This function is used to asynchronously send data on the datagram socket. 310 * The function call always returns immediately. 311 * 312 * @param buffers One or more data buffers to be sent on the socket. Although 313 * the buffers object may be copied as necessary, ownership of the underlying 314 * memory blocks is retained by the caller, which must guarantee that they 315 * remain valid until the handler is called. 316 * 317 * @param handler The handler to be called when the send operation completes. 318 * Copies will be made of the handler as required. The function signature of 319 * the handler must be: 320 * @code void handler( 321 * const asio::error_code& error, // Result of operation. 322 * std::size_t bytes_transferred // Number of bytes sent. 323 * ); @endcode 324 * Regardless of whether the asynchronous operation completes immediately or 325 * not, the handler will not be invoked from within this function. Invocation 326 * of the handler will be performed in a manner equivalent to using 327 * asio::io_context::post(). 328 * 329 * @note The async_send operation can only be used with a connected socket. 330 * Use the async_send_to function to send data on an unconnected datagram 331 * socket. 332 * 333 * @par Example 334 * To send a single data buffer use the @ref buffer function as follows: 335 * @code 336 * socket.async_send(asio::buffer(data, size), handler); 337 * @endcode 338 * See the @ref buffer documentation for information on sending multiple 339 * buffers in one go, and how to use it with arrays, boost::array or 340 * std::vector. 341 */ 342 template <typename ConstBufferSequence, typename WriteHandler> ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))343 ASIO_INITFN_RESULT_TYPE(WriteHandler, 344 void (asio::error_code, std::size_t)) 345 async_send(const ConstBufferSequence& buffers, 346 ASIO_MOVE_ARG(WriteHandler) handler) 347 { 348 // If you get an error on the following line it means that your handler does 349 // not meet the documented type requirements for a WriteHandler. 350 ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 351 352 #if defined(ASIO_ENABLE_OLD_SERVICES) 353 return this->get_service().async_send(this->get_implementation(), 354 buffers, 0, ASIO_MOVE_CAST(WriteHandler)(handler)); 355 #else // defined(ASIO_ENABLE_OLD_SERVICES) 356 async_completion<WriteHandler, 357 void (asio::error_code, std::size_t)> init(handler); 358 359 this->get_service().async_send(this->get_implementation(), 360 buffers, 0, init.completion_handler); 361 362 return init.result.get(); 363 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 364 } 365 366 /// Start an asynchronous send on a connected socket. 367 /** 368 * This function is used to asynchronously send data on the datagram socket. 369 * The function call always returns immediately. 370 * 371 * @param buffers One or more data buffers to be sent on the socket. Although 372 * the buffers object may be copied as necessary, ownership of the underlying 373 * memory blocks is retained by the caller, which must guarantee that they 374 * remain valid until the handler is called. 375 * 376 * @param flags Flags specifying how the send call is to be made. 377 * 378 * @param handler The handler to be called when the send operation completes. 379 * Copies will be made of the handler as required. The function signature of 380 * the handler must be: 381 * @code void handler( 382 * const asio::error_code& error, // Result of operation. 383 * std::size_t bytes_transferred // Number of bytes sent. 384 * ); @endcode 385 * Regardless of whether the asynchronous operation completes immediately or 386 * not, the handler will not be invoked from within this function. Invocation 387 * of the handler will be performed in a manner equivalent to using 388 * asio::io_context::post(). 389 * 390 * @note The async_send operation can only be used with a connected socket. 391 * Use the async_send_to function to send data on an unconnected datagram 392 * socket. 393 */ 394 template <typename ConstBufferSequence, typename WriteHandler> ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))395 ASIO_INITFN_RESULT_TYPE(WriteHandler, 396 void (asio::error_code, std::size_t)) 397 async_send(const ConstBufferSequence& buffers, 398 socket_base::message_flags flags, 399 ASIO_MOVE_ARG(WriteHandler) handler) 400 { 401 // If you get an error on the following line it means that your handler does 402 // not meet the documented type requirements for a WriteHandler. 403 ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 404 405 #if defined(ASIO_ENABLE_OLD_SERVICES) 406 return this->get_service().async_send(this->get_implementation(), 407 buffers, flags, ASIO_MOVE_CAST(WriteHandler)(handler)); 408 #else // defined(ASIO_ENABLE_OLD_SERVICES) 409 async_completion<WriteHandler, 410 void (asio::error_code, std::size_t)> init(handler); 411 412 this->get_service().async_send(this->get_implementation(), 413 buffers, flags, init.completion_handler); 414 415 return init.result.get(); 416 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 417 } 418 419 /// Send a datagram to the specified endpoint. 420 /** 421 * This function is used to send a datagram to the specified remote endpoint. 422 * The function call will block until the data has been sent successfully or 423 * an error occurs. 424 * 425 * @param buffers One or more data buffers to be sent to the remote endpoint. 426 * 427 * @param destination The remote endpoint to which the data will be sent. 428 * 429 * @returns The number of bytes sent. 430 * 431 * @throws asio::system_error Thrown on failure. 432 * 433 * @par Example 434 * To send a single data buffer use the @ref buffer function as follows: 435 * @code 436 * asio::ip::udp::endpoint destination( 437 * asio::ip::address::from_string("1.2.3.4"), 12345); 438 * socket.send_to(asio::buffer(data, size), destination); 439 * @endcode 440 * See the @ref buffer documentation for information on sending multiple 441 * buffers in one go, and how to use it with arrays, boost::array or 442 * std::vector. 443 */ 444 template <typename ConstBufferSequence> send_to(const ConstBufferSequence & buffers,const endpoint_type & destination)445 std::size_t send_to(const ConstBufferSequence& buffers, 446 const endpoint_type& destination) 447 { 448 asio::error_code ec; 449 std::size_t s = this->get_service().send_to( 450 this->get_implementation(), buffers, destination, 0, ec); 451 asio::detail::throw_error(ec, "send_to"); 452 return s; 453 } 454 455 /// Send a datagram to the specified endpoint. 456 /** 457 * This function is used to send a datagram to the specified remote endpoint. 458 * The function call will block until the data has been sent successfully or 459 * an error occurs. 460 * 461 * @param buffers One or more data buffers to be sent to the remote endpoint. 462 * 463 * @param destination The remote endpoint to which the data will be sent. 464 * 465 * @param flags Flags specifying how the send call is to be made. 466 * 467 * @returns The number of bytes sent. 468 * 469 * @throws asio::system_error Thrown on failure. 470 */ 471 template <typename ConstBufferSequence> send_to(const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags)472 std::size_t send_to(const ConstBufferSequence& buffers, 473 const endpoint_type& destination, socket_base::message_flags flags) 474 { 475 asio::error_code ec; 476 std::size_t s = this->get_service().send_to( 477 this->get_implementation(), buffers, destination, flags, ec); 478 asio::detail::throw_error(ec, "send_to"); 479 return s; 480 } 481 482 /// Send a datagram to the specified endpoint. 483 /** 484 * This function is used to send a datagram to the specified remote endpoint. 485 * The function call will block until the data has been sent successfully or 486 * an error occurs. 487 * 488 * @param buffers One or more data buffers to be sent to the remote endpoint. 489 * 490 * @param destination The remote endpoint to which the data will be sent. 491 * 492 * @param flags Flags specifying how the send call is to be made. 493 * 494 * @param ec Set to indicate what error occurred, if any. 495 * 496 * @returns The number of bytes sent. 497 */ 498 template <typename ConstBufferSequence> send_to(const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags,asio::error_code & ec)499 std::size_t send_to(const ConstBufferSequence& buffers, 500 const endpoint_type& destination, socket_base::message_flags flags, 501 asio::error_code& ec) 502 { 503 return this->get_service().send_to(this->get_implementation(), 504 buffers, destination, flags, ec); 505 } 506 507 /// Start an asynchronous send. 508 /** 509 * This function is used to asynchronously send a datagram to the specified 510 * remote endpoint. The function call always returns immediately. 511 * 512 * @param buffers One or more data buffers to be sent to the remote endpoint. 513 * Although the buffers object may be copied as necessary, ownership of the 514 * underlying memory blocks is retained by the caller, which must guarantee 515 * that they remain valid until the handler is called. 516 * 517 * @param destination The remote endpoint to which the data will be sent. 518 * Copies will be made of the endpoint as required. 519 * 520 * @param handler The handler to be called when the send operation completes. 521 * Copies will be made of the handler as required. The function signature of 522 * the handler must be: 523 * @code void handler( 524 * const asio::error_code& error, // Result of operation. 525 * std::size_t bytes_transferred // Number of bytes sent. 526 * ); @endcode 527 * Regardless of whether the asynchronous operation completes immediately or 528 * not, the handler will not be invoked from within this function. Invocation 529 * of the handler will be performed in a manner equivalent to using 530 * asio::io_context::post(). 531 * 532 * @par Example 533 * To send a single data buffer use the @ref buffer function as follows: 534 * @code 535 * asio::ip::udp::endpoint destination( 536 * asio::ip::address::from_string("1.2.3.4"), 12345); 537 * socket.async_send_to( 538 * asio::buffer(data, size), destination, handler); 539 * @endcode 540 * See the @ref buffer documentation for information on sending multiple 541 * buffers in one go, and how to use it with arrays, boost::array or 542 * std::vector. 543 */ 544 template <typename ConstBufferSequence, typename WriteHandler> ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))545 ASIO_INITFN_RESULT_TYPE(WriteHandler, 546 void (asio::error_code, std::size_t)) 547 async_send_to(const ConstBufferSequence& buffers, 548 const endpoint_type& destination, 549 ASIO_MOVE_ARG(WriteHandler) handler) 550 { 551 // If you get an error on the following line it means that your handler does 552 // not meet the documented type requirements for a WriteHandler. 553 ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 554 555 #if defined(ASIO_ENABLE_OLD_SERVICES) 556 return this->get_service().async_send_to( 557 this->get_implementation(), buffers, destination, 0, 558 ASIO_MOVE_CAST(WriteHandler)(handler)); 559 #else // defined(ASIO_ENABLE_OLD_SERVICES) 560 async_completion<WriteHandler, 561 void (asio::error_code, std::size_t)> init(handler); 562 563 this->get_service().async_send_to( 564 this->get_implementation(), buffers, destination, 0, 565 init.completion_handler); 566 567 return init.result.get(); 568 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 569 } 570 571 /// Start an asynchronous send. 572 /** 573 * This function is used to asynchronously send a datagram to the specified 574 * remote endpoint. The function call always returns immediately. 575 * 576 * @param buffers One or more data buffers to be sent to the remote endpoint. 577 * Although the buffers object may be copied as necessary, ownership of the 578 * underlying memory blocks is retained by the caller, which must guarantee 579 * that they remain valid until the handler is called. 580 * 581 * @param flags Flags specifying how the send call is to be made. 582 * 583 * @param destination The remote endpoint to which the data will be sent. 584 * Copies will be made of the endpoint as required. 585 * 586 * @param handler The handler to be called when the send operation completes. 587 * Copies will be made of the handler as required. The function signature of 588 * the handler must be: 589 * @code void handler( 590 * const asio::error_code& error, // Result of operation. 591 * std::size_t bytes_transferred // Number of bytes sent. 592 * ); @endcode 593 * Regardless of whether the asynchronous operation completes immediately or 594 * not, the handler will not be invoked from within this function. Invocation 595 * of the handler will be performed in a manner equivalent to using 596 * asio::io_context::post(). 597 */ 598 template <typename ConstBufferSequence, typename WriteHandler> ASIO_INITFN_RESULT_TYPE(WriteHandler,void (asio::error_code,std::size_t))599 ASIO_INITFN_RESULT_TYPE(WriteHandler, 600 void (asio::error_code, std::size_t)) 601 async_send_to(const ConstBufferSequence& buffers, 602 const endpoint_type& destination, socket_base::message_flags flags, 603 ASIO_MOVE_ARG(WriteHandler) handler) 604 { 605 // If you get an error on the following line it means that your handler does 606 // not meet the documented type requirements for a WriteHandler. 607 ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; 608 609 #if defined(ASIO_ENABLE_OLD_SERVICES) 610 return this->get_service().async_send_to( 611 this->get_implementation(), buffers, destination, flags, 612 ASIO_MOVE_CAST(WriteHandler)(handler)); 613 #else // defined(ASIO_ENABLE_OLD_SERVICES) 614 async_completion<WriteHandler, 615 void (asio::error_code, std::size_t)> init(handler); 616 617 this->get_service().async_send_to( 618 this->get_implementation(), buffers, destination, flags, 619 init.completion_handler); 620 621 return init.result.get(); 622 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 623 } 624 625 /// Receive some data on a connected socket. 626 /** 627 * This function is used to receive data on the datagram socket. The function 628 * call will block until data has been received successfully or an error 629 * occurs. 630 * 631 * @param buffers One or more buffers into which the data will be received. 632 * 633 * @returns The number of bytes received. 634 * 635 * @throws asio::system_error Thrown on failure. 636 * 637 * @note The receive operation can only be used with a connected socket. Use 638 * the receive_from function to receive data on an unconnected datagram 639 * socket. 640 * 641 * @par Example 642 * To receive into a single data buffer use the @ref buffer function as 643 * follows: 644 * @code socket.receive(asio::buffer(data, size)); @endcode 645 * See the @ref buffer documentation for information on receiving into 646 * multiple buffers in one go, and how to use it with arrays, boost::array or 647 * std::vector. 648 */ 649 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers)650 std::size_t receive(const MutableBufferSequence& buffers) 651 { 652 asio::error_code ec; 653 std::size_t s = this->get_service().receive( 654 this->get_implementation(), buffers, 0, ec); 655 asio::detail::throw_error(ec, "receive"); 656 return s; 657 } 658 659 /// Receive some data on a connected socket. 660 /** 661 * This function is used to receive data on the datagram socket. The function 662 * call will block until data has been received successfully or an error 663 * occurs. 664 * 665 * @param buffers One or more buffers into which the data will be received. 666 * 667 * @param flags Flags specifying how the receive call is to be made. 668 * 669 * @returns The number of bytes received. 670 * 671 * @throws asio::system_error Thrown on failure. 672 * 673 * @note The receive operation can only be used with a connected socket. Use 674 * the receive_from function to receive data on an unconnected datagram 675 * socket. 676 */ 677 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers,socket_base::message_flags flags)678 std::size_t receive(const MutableBufferSequence& buffers, 679 socket_base::message_flags flags) 680 { 681 asio::error_code ec; 682 std::size_t s = this->get_service().receive( 683 this->get_implementation(), buffers, flags, ec); 684 asio::detail::throw_error(ec, "receive"); 685 return s; 686 } 687 688 /// Receive some data on a connected socket. 689 /** 690 * This function is used to receive data on the datagram socket. The function 691 * call will block until data has been received successfully or an error 692 * occurs. 693 * 694 * @param buffers One or more buffers into which the data will be received. 695 * 696 * @param flags Flags specifying how the receive call is to be made. 697 * 698 * @param ec Set to indicate what error occurred, if any. 699 * 700 * @returns The number of bytes received. 701 * 702 * @note The receive operation can only be used with a connected socket. Use 703 * the receive_from function to receive data on an unconnected datagram 704 * socket. 705 */ 706 template <typename MutableBufferSequence> receive(const MutableBufferSequence & buffers,socket_base::message_flags flags,asio::error_code & ec)707 std::size_t receive(const MutableBufferSequence& buffers, 708 socket_base::message_flags flags, asio::error_code& ec) 709 { 710 return this->get_service().receive( 711 this->get_implementation(), buffers, flags, ec); 712 } 713 714 /// Start an asynchronous receive on a connected socket. 715 /** 716 * This function is used to asynchronously receive data from the datagram 717 * socket. The function call always returns immediately. 718 * 719 * @param buffers One or more buffers into which the data will be received. 720 * Although the buffers object may be copied as necessary, ownership of the 721 * underlying memory blocks is retained by the caller, which must guarantee 722 * that they remain valid until the handler is called. 723 * 724 * @param handler The handler to be called when the receive operation 725 * completes. Copies will be made of the handler as required. The function 726 * signature of the handler must be: 727 * @code void handler( 728 * const asio::error_code& error, // Result of operation. 729 * std::size_t bytes_transferred // Number of bytes received. 730 * ); @endcode 731 * Regardless of whether the asynchronous operation completes immediately or 732 * not, the handler will not be invoked from within this function. Invocation 733 * of the handler will be performed in a manner equivalent to using 734 * asio::io_context::post(). 735 * 736 * @note The async_receive operation can only be used with a connected socket. 737 * Use the async_receive_from function to receive data on an unconnected 738 * datagram socket. 739 * 740 * @par Example 741 * To receive into a single data buffer use the @ref buffer function as 742 * follows: 743 * @code 744 * socket.async_receive(asio::buffer(data, size), handler); 745 * @endcode 746 * See the @ref buffer documentation for information on receiving into 747 * multiple buffers in one go, and how to use it with arrays, boost::array or 748 * std::vector. 749 */ 750 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))751 ASIO_INITFN_RESULT_TYPE(ReadHandler, 752 void (asio::error_code, std::size_t)) 753 async_receive(const MutableBufferSequence& buffers, 754 ASIO_MOVE_ARG(ReadHandler) handler) 755 { 756 // If you get an error on the following line it means that your handler does 757 // not meet the documented type requirements for a ReadHandler. 758 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 759 760 #if defined(ASIO_ENABLE_OLD_SERVICES) 761 return this->get_service().async_receive(this->get_implementation(), 762 buffers, 0, ASIO_MOVE_CAST(ReadHandler)(handler)); 763 #else // defined(ASIO_ENABLE_OLD_SERVICES) 764 async_completion<ReadHandler, 765 void (asio::error_code, std::size_t)> init(handler); 766 767 this->get_service().async_receive(this->get_implementation(), 768 buffers, 0, init.completion_handler); 769 770 return init.result.get(); 771 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 772 } 773 774 /// Start an asynchronous receive on a connected socket. 775 /** 776 * This function is used to asynchronously receive data from the datagram 777 * socket. The function call always returns immediately. 778 * 779 * @param buffers One or more buffers into which the data will be received. 780 * Although the buffers object may be copied as necessary, ownership of the 781 * underlying memory blocks is retained by the caller, which must guarantee 782 * that they remain valid until the handler is called. 783 * 784 * @param flags Flags specifying how the receive call is to be made. 785 * 786 * @param handler The handler to be called when the receive operation 787 * completes. Copies will be made of the handler as required. The function 788 * signature of the handler must be: 789 * @code void handler( 790 * const asio::error_code& error, // Result of operation. 791 * std::size_t bytes_transferred // Number of bytes received. 792 * ); @endcode 793 * Regardless of whether the asynchronous operation completes immediately or 794 * not, the handler will not be invoked from within this function. Invocation 795 * of the handler will be performed in a manner equivalent to using 796 * asio::io_context::post(). 797 * 798 * @note The async_receive operation can only be used with a connected socket. 799 * Use the async_receive_from function to receive data on an unconnected 800 * datagram socket. 801 */ 802 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))803 ASIO_INITFN_RESULT_TYPE(ReadHandler, 804 void (asio::error_code, std::size_t)) 805 async_receive(const MutableBufferSequence& buffers, 806 socket_base::message_flags flags, 807 ASIO_MOVE_ARG(ReadHandler) handler) 808 { 809 // If you get an error on the following line it means that your handler does 810 // not meet the documented type requirements for a ReadHandler. 811 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 812 813 #if defined(ASIO_ENABLE_OLD_SERVICES) 814 return this->get_service().async_receive(this->get_implementation(), 815 buffers, flags, ASIO_MOVE_CAST(ReadHandler)(handler)); 816 #else // defined(ASIO_ENABLE_OLD_SERVICES) 817 async_completion<ReadHandler, 818 void (asio::error_code, std::size_t)> init(handler); 819 820 this->get_service().async_receive(this->get_implementation(), 821 buffers, flags, init.completion_handler); 822 823 return init.result.get(); 824 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 825 } 826 827 /// Receive a datagram with the endpoint of the sender. 828 /** 829 * This function is used to receive a datagram. The function call will block 830 * until data has been received successfully or an error occurs. 831 * 832 * @param buffers One or more buffers into which the data will be received. 833 * 834 * @param sender_endpoint An endpoint object that receives the endpoint of 835 * the remote sender of the datagram. 836 * 837 * @returns The number of bytes received. 838 * 839 * @throws asio::system_error Thrown on failure. 840 * 841 * @par Example 842 * To receive into a single data buffer use the @ref buffer function as 843 * follows: 844 * @code 845 * asio::ip::udp::endpoint sender_endpoint; 846 * socket.receive_from( 847 * asio::buffer(data, size), sender_endpoint); 848 * @endcode 849 * See the @ref buffer documentation for information on receiving into 850 * multiple buffers in one go, and how to use it with arrays, boost::array or 851 * std::vector. 852 */ 853 template <typename MutableBufferSequence> receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint)854 std::size_t receive_from(const MutableBufferSequence& buffers, 855 endpoint_type& sender_endpoint) 856 { 857 asio::error_code ec; 858 std::size_t s = this->get_service().receive_from( 859 this->get_implementation(), buffers, sender_endpoint, 0, ec); 860 asio::detail::throw_error(ec, "receive_from"); 861 return s; 862 } 863 864 /// Receive a datagram with the endpoint of the sender. 865 /** 866 * This function is used to receive a datagram. The function call will block 867 * until data has been received successfully or an error occurs. 868 * 869 * @param buffers One or more buffers into which the data will be received. 870 * 871 * @param sender_endpoint An endpoint object that receives the endpoint of 872 * the remote sender of the datagram. 873 * 874 * @param flags Flags specifying how the receive call is to be made. 875 * 876 * @returns The number of bytes received. 877 * 878 * @throws asio::system_error Thrown on failure. 879 */ 880 template <typename MutableBufferSequence> receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags)881 std::size_t receive_from(const MutableBufferSequence& buffers, 882 endpoint_type& sender_endpoint, socket_base::message_flags flags) 883 { 884 asio::error_code ec; 885 std::size_t s = this->get_service().receive_from( 886 this->get_implementation(), buffers, sender_endpoint, flags, ec); 887 asio::detail::throw_error(ec, "receive_from"); 888 return s; 889 } 890 891 /// Receive a datagram with the endpoint of the sender. 892 /** 893 * This function is used to receive a datagram. The function call will block 894 * until data has been received successfully or an error occurs. 895 * 896 * @param buffers One or more buffers into which the data will be received. 897 * 898 * @param sender_endpoint An endpoint object that receives the endpoint of 899 * the remote sender of the datagram. 900 * 901 * @param flags Flags specifying how the receive call is to be made. 902 * 903 * @param ec Set to indicate what error occurred, if any. 904 * 905 * @returns The number of bytes received. 906 */ 907 template <typename MutableBufferSequence> receive_from(const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags,asio::error_code & ec)908 std::size_t receive_from(const MutableBufferSequence& buffers, 909 endpoint_type& sender_endpoint, socket_base::message_flags flags, 910 asio::error_code& ec) 911 { 912 return this->get_service().receive_from(this->get_implementation(), 913 buffers, sender_endpoint, flags, ec); 914 } 915 916 /// Start an asynchronous receive. 917 /** 918 * This function is used to asynchronously receive a datagram. The function 919 * call always returns immediately. 920 * 921 * @param buffers One or more buffers into which the data will be received. 922 * Although the buffers object may be copied as necessary, ownership of the 923 * underlying memory blocks is retained by the caller, which must guarantee 924 * that they remain valid until the handler is called. 925 * 926 * @param sender_endpoint An endpoint object that receives the endpoint of 927 * the remote sender of the datagram. Ownership of the sender_endpoint object 928 * is retained by the caller, which must guarantee that it is valid until the 929 * handler is called. 930 * 931 * @param handler The handler to be called when the receive operation 932 * completes. Copies will be made of the handler as required. The function 933 * signature of the handler must be: 934 * @code void handler( 935 * const asio::error_code& error, // Result of operation. 936 * std::size_t bytes_transferred // Number of bytes received. 937 * ); @endcode 938 * Regardless of whether the asynchronous operation completes immediately or 939 * not, the handler will not be invoked from within this function. Invocation 940 * of the handler will be performed in a manner equivalent to using 941 * asio::io_context::post(). 942 * 943 * @par Example 944 * To receive into a single data buffer use the @ref buffer function as 945 * follows: 946 * @code socket.async_receive_from( 947 * asio::buffer(data, size), sender_endpoint, handler); @endcode 948 * See the @ref buffer documentation for information on receiving into 949 * multiple buffers in one go, and how to use it with arrays, boost::array or 950 * std::vector. 951 */ 952 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))953 ASIO_INITFN_RESULT_TYPE(ReadHandler, 954 void (asio::error_code, std::size_t)) 955 async_receive_from(const MutableBufferSequence& buffers, 956 endpoint_type& sender_endpoint, 957 ASIO_MOVE_ARG(ReadHandler) handler) 958 { 959 // If you get an error on the following line it means that your handler does 960 // not meet the documented type requirements for a ReadHandler. 961 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 962 963 #if defined(ASIO_ENABLE_OLD_SERVICES) 964 return this->get_service().async_receive_from( 965 this->get_implementation(), buffers, sender_endpoint, 0, 966 ASIO_MOVE_CAST(ReadHandler)(handler)); 967 #else // defined(ASIO_ENABLE_OLD_SERVICES) 968 async_completion<ReadHandler, 969 void (asio::error_code, std::size_t)> init(handler); 970 971 this->get_service().async_receive_from( 972 this->get_implementation(), buffers, sender_endpoint, 0, 973 init.completion_handler); 974 975 return init.result.get(); 976 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 977 } 978 979 /// Start an asynchronous receive. 980 /** 981 * This function is used to asynchronously receive a datagram. The function 982 * call always returns immediately. 983 * 984 * @param buffers One or more buffers into which the data will be received. 985 * Although the buffers object may be copied as necessary, ownership of the 986 * underlying memory blocks is retained by the caller, which must guarantee 987 * that they remain valid until the handler is called. 988 * 989 * @param sender_endpoint An endpoint object that receives the endpoint of 990 * the remote sender of the datagram. Ownership of the sender_endpoint object 991 * is retained by the caller, which must guarantee that it is valid until the 992 * handler is called. 993 * 994 * @param flags Flags specifying how the receive call is to be made. 995 * 996 * @param handler The handler to be called when the receive operation 997 * completes. Copies will be made of the handler as required. The function 998 * signature of the handler must be: 999 * @code void handler( 1000 * const asio::error_code& error, // Result of operation. 1001 * std::size_t bytes_transferred // Number of bytes received. 1002 * ); @endcode 1003 * Regardless of whether the asynchronous operation completes immediately or 1004 * not, the handler will not be invoked from within this function. Invocation 1005 * of the handler will be performed in a manner equivalent to using 1006 * asio::io_context::post(). 1007 */ 1008 template <typename MutableBufferSequence, typename ReadHandler> ASIO_INITFN_RESULT_TYPE(ReadHandler,void (asio::error_code,std::size_t))1009 ASIO_INITFN_RESULT_TYPE(ReadHandler, 1010 void (asio::error_code, std::size_t)) 1011 async_receive_from(const MutableBufferSequence& buffers, 1012 endpoint_type& sender_endpoint, socket_base::message_flags flags, 1013 ASIO_MOVE_ARG(ReadHandler) handler) 1014 { 1015 // If you get an error on the following line it means that your handler does 1016 // not meet the documented type requirements for a ReadHandler. 1017 ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; 1018 1019 #if defined(ASIO_ENABLE_OLD_SERVICES) 1020 return this->get_service().async_receive_from( 1021 this->get_implementation(), buffers, sender_endpoint, flags, 1022 ASIO_MOVE_CAST(ReadHandler)(handler)); 1023 #else // defined(ASIO_ENABLE_OLD_SERVICES) 1024 async_completion<ReadHandler, 1025 void (asio::error_code, std::size_t)> init(handler); 1026 1027 this->get_service().async_receive_from( 1028 this->get_implementation(), buffers, sender_endpoint, flags, 1029 init.completion_handler); 1030 1031 return init.result.get(); 1032 #endif // defined(ASIO_ENABLE_OLD_SERVICES) 1033 } 1034 }; 1035 1036 } // namespace asio 1037 1038 #include "asio/detail/pop_options.hpp" 1039 1040 #endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP 1041