1 // 2 // basic_socket.hpp 3 // ~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2017 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 BOOST_ASIO_BASIC_SOCKET_HPP 12 #define BOOST_ASIO_BASIC_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 <boost/asio/detail/config.hpp> 19 #include <boost/asio/async_result.hpp> 20 #include <boost/asio/basic_io_object.hpp> 21 #include <boost/asio/detail/handler_type_requirements.hpp> 22 #include <boost/asio/detail/throw_error.hpp> 23 #include <boost/asio/detail/type_traits.hpp> 24 #include <boost/asio/error.hpp> 25 #include <boost/asio/post.hpp> 26 #include <boost/asio/socket_base.hpp> 27 28 #if defined(BOOST_ASIO_HAS_MOVE) 29 # include <utility> 30 #endif // defined(BOOST_ASIO_HAS_MOVE) 31 32 #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 33 # if defined(BOOST_ASIO_WINDOWS_RUNTIME) 34 # include <boost/asio/detail/winrt_ssocket_service.hpp> 35 # define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol> 36 # elif defined(BOOST_ASIO_HAS_IOCP) 37 # include <boost/asio/detail/win_iocp_socket_service.hpp> 38 # define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol> 39 # else 40 # include <boost/asio/detail/reactive_socket_service.hpp> 41 # define BOOST_ASIO_SVC_T detail::reactive_socket_service<Protocol> 42 # endif 43 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 44 45 #include <boost/asio/detail/push_options.hpp> 46 47 namespace boost { 48 namespace asio { 49 50 /// Provides socket functionality. 51 /** 52 * The basic_socket class template provides functionality that is common to both 53 * stream-oriented and datagram-oriented sockets. 54 * 55 * @par Thread Safety 56 * @e Distinct @e objects: Safe.@n 57 * @e Shared @e objects: Unsafe. 58 */ 59 template <typename Protocol BOOST_ASIO_SVC_TPARAM> 60 class basic_socket 61 : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>, 62 public socket_base 63 { 64 public: 65 /// The type of the executor associated with the object. 66 typedef io_context::executor_type executor_type; 67 68 /// The native representation of a socket. 69 #if defined(GENERATING_DOCUMENTATION) 70 typedef implementation_defined native_handle_type; 71 #else 72 typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type; 73 #endif 74 75 /// The protocol type. 76 typedef Protocol protocol_type; 77 78 /// The endpoint type. 79 typedef typename Protocol::endpoint endpoint_type; 80 81 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 82 /// A basic_socket is always the lowest layer. 83 typedef basic_socket<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type; 84 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 85 86 /// Construct a basic_socket without opening it. 87 /** 88 * This constructor creates a socket without opening it. 89 * 90 * @param io_context The io_context object that the socket will use to 91 * dispatch handlers for any asynchronous operations performed on the socket. 92 */ basic_socket(boost::asio::io_context & io_context)93 explicit basic_socket(boost::asio::io_context& io_context) 94 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 95 { 96 } 97 98 /// Construct and open a basic_socket. 99 /** 100 * This constructor creates and opens a socket. 101 * 102 * @param io_context The io_context object that the socket will use to 103 * dispatch handlers for any asynchronous operations performed on the socket. 104 * 105 * @param protocol An object specifying protocol parameters to be used. 106 * 107 * @throws boost::system::system_error Thrown on failure. 108 */ basic_socket(boost::asio::io_context & io_context,const protocol_type & protocol)109 basic_socket(boost::asio::io_context& io_context, 110 const protocol_type& protocol) 111 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 112 { 113 boost::system::error_code ec; 114 this->get_service().open(this->get_implementation(), protocol, ec); 115 boost::asio::detail::throw_error(ec, "open"); 116 } 117 118 /// Construct a basic_socket, opening it and binding it to the given local 119 /// endpoint. 120 /** 121 * This constructor creates a socket and automatically opens it bound to the 122 * specified endpoint on the local machine. The protocol used is the protocol 123 * associated with the given endpoint. 124 * 125 * @param io_context The io_context object that the socket will use to 126 * dispatch handlers for any asynchronous operations performed on the socket. 127 * 128 * @param endpoint An endpoint on the local machine to which the socket will 129 * be bound. 130 * 131 * @throws boost::system::system_error Thrown on failure. 132 */ basic_socket(boost::asio::io_context & io_context,const endpoint_type & endpoint)133 basic_socket(boost::asio::io_context& io_context, 134 const endpoint_type& endpoint) 135 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 136 { 137 boost::system::error_code ec; 138 const protocol_type protocol = endpoint.protocol(); 139 this->get_service().open(this->get_implementation(), protocol, ec); 140 boost::asio::detail::throw_error(ec, "open"); 141 this->get_service().bind(this->get_implementation(), endpoint, ec); 142 boost::asio::detail::throw_error(ec, "bind"); 143 } 144 145 /// Construct a basic_socket on an existing native socket. 146 /** 147 * This constructor creates a socket object to hold an existing native socket. 148 * 149 * @param io_context The io_context object that the socket will use to 150 * dispatch handlers for any asynchronous operations performed on the socket. 151 * 152 * @param protocol An object specifying protocol parameters to be used. 153 * 154 * @param native_socket A native socket. 155 * 156 * @throws boost::system::system_error Thrown on failure. 157 */ basic_socket(boost::asio::io_context & io_context,const protocol_type & protocol,const native_handle_type & native_socket)158 basic_socket(boost::asio::io_context& io_context, 159 const protocol_type& protocol, const native_handle_type& native_socket) 160 : basic_io_object<BOOST_ASIO_SVC_T>(io_context) 161 { 162 boost::system::error_code ec; 163 this->get_service().assign(this->get_implementation(), 164 protocol, native_socket, ec); 165 boost::asio::detail::throw_error(ec, "assign"); 166 } 167 168 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 169 /// Move-construct a basic_socket from another. 170 /** 171 * This constructor moves a socket from one object to another. 172 * 173 * @param other The other basic_socket object from which the move will 174 * occur. 175 * 176 * @note Following the move, the moved-from object is in the same state as if 177 * constructed using the @c basic_socket(io_context&) constructor. 178 */ basic_socket(basic_socket && other)179 basic_socket(basic_socket&& other) 180 : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other)) 181 { 182 } 183 184 /// Move-assign a basic_socket from another. 185 /** 186 * This assignment operator moves a socket from one object to another. 187 * 188 * @param other The other basic_socket object from which the move will 189 * occur. 190 * 191 * @note Following the move, the moved-from object is in the same state as if 192 * constructed using the @c basic_socket(io_context&) constructor. 193 */ operator =(basic_socket && other)194 basic_socket& operator=(basic_socket&& other) 195 { 196 basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other)); 197 return *this; 198 } 199 200 // All sockets have access to each other's implementations. 201 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> 202 friend class basic_socket; 203 204 /// Move-construct a basic_socket from a socket of another protocol type. 205 /** 206 * This constructor moves a socket from one object to another. 207 * 208 * @param other The other basic_socket object from which the move will 209 * occur. 210 * 211 * @note Following the move, the moved-from object is in the same state as if 212 * constructed using the @c basic_socket(io_context&) constructor. 213 */ 214 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> basic_socket(basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1> && other,typename enable_if<is_convertible<Protocol1,Protocol>::value>::type * =0)215 basic_socket(basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other, 216 typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) 217 : basic_io_object<BOOST_ASIO_SVC_T>( 218 other.get_service(), other.get_implementation()) 219 { 220 } 221 222 /// Move-assign a basic_socket from a socket of another protocol type. 223 /** 224 * This assignment operator moves a socket from one object to another. 225 * 226 * @param other The other basic_socket object from which the move will 227 * occur. 228 * 229 * @note Following the move, the moved-from object is in the same state as if 230 * constructed using the @c basic_socket(io_context&) constructor. 231 */ 232 template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1> 233 typename enable_if<is_convertible<Protocol1, Protocol>::value, operator =(basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1> && other)234 basic_socket>::type& operator=( 235 basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other) 236 { 237 basic_socket tmp(std::move(other)); 238 basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp)); 239 return *this; 240 } 241 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 242 243 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 244 // These functions are provided by basic_io_object<>. 245 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 246 #if !defined(BOOST_ASIO_NO_DEPRECATED) 247 /// (Deprecated: Use get_executor().) Get the io_context associated with the 248 /// object. 249 /** 250 * This function may be used to obtain the io_context object that the I/O 251 * object uses to dispatch handlers for asynchronous operations. 252 * 253 * @return A reference to the io_context object that the I/O object will use 254 * to dispatch handlers. Ownership is not transferred to the caller. 255 */ get_io_context()256 boost::asio::io_context& get_io_context() 257 { 258 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context(); 259 } 260 261 /// (Deprecated: Use get_executor().) Get the io_context associated with the 262 /// object. 263 /** 264 * This function may be used to obtain the io_context object that the I/O 265 * object uses to dispatch handlers for asynchronous operations. 266 * 267 * @return A reference to the io_context object that the I/O object will use 268 * to dispatch handlers. Ownership is not transferred to the caller. 269 */ get_io_service()270 boost::asio::io_context& get_io_service() 271 { 272 return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service(); 273 } 274 #endif // !defined(BOOST_ASIO_NO_DEPRECATED) 275 276 /// Get the executor associated with the object. get_executor()277 executor_type get_executor() BOOST_ASIO_NOEXCEPT 278 { 279 return basic_io_object<BOOST_ASIO_SVC_T>::get_executor(); 280 } 281 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 282 283 #if !defined(BOOST_ASIO_NO_EXTENSIONS) 284 /// Get a reference to the lowest layer. 285 /** 286 * This function returns a reference to the lowest layer in a stack of 287 * layers. Since a basic_socket cannot contain any further layers, it simply 288 * returns a reference to itself. 289 * 290 * @return A reference to the lowest layer in the stack of layers. Ownership 291 * is not transferred to the caller. 292 */ lowest_layer()293 lowest_layer_type& lowest_layer() 294 { 295 return *this; 296 } 297 298 /// Get a const reference to the lowest layer. 299 /** 300 * This function returns a const reference to the lowest layer in a stack of 301 * layers. Since a basic_socket cannot contain any further layers, it simply 302 * returns a reference to itself. 303 * 304 * @return A const reference to the lowest layer in the stack of layers. 305 * Ownership is not transferred to the caller. 306 */ lowest_layer() const307 const lowest_layer_type& lowest_layer() const 308 { 309 return *this; 310 } 311 #endif // !defined(BOOST_ASIO_NO_EXTENSIONS) 312 313 /// Open the socket using the specified protocol. 314 /** 315 * This function opens the socket so that it will use the specified protocol. 316 * 317 * @param protocol An object specifying protocol parameters to be used. 318 * 319 * @throws boost::system::system_error Thrown on failure. 320 * 321 * @par Example 322 * @code 323 * boost::asio::ip::tcp::socket socket(io_context); 324 * socket.open(boost::asio::ip::tcp::v4()); 325 * @endcode 326 */ open(const protocol_type & protocol=protocol_type ())327 void open(const protocol_type& protocol = protocol_type()) 328 { 329 boost::system::error_code ec; 330 this->get_service().open(this->get_implementation(), protocol, ec); 331 boost::asio::detail::throw_error(ec, "open"); 332 } 333 334 /// Open the socket using the specified protocol. 335 /** 336 * This function opens the socket so that it will use the specified protocol. 337 * 338 * @param protocol An object specifying which protocol is to be used. 339 * 340 * @param ec Set to indicate what error occurred, if any. 341 * 342 * @par Example 343 * @code 344 * boost::asio::ip::tcp::socket socket(io_context); 345 * boost::system::error_code ec; 346 * socket.open(boost::asio::ip::tcp::v4(), ec); 347 * if (ec) 348 * { 349 * // An error occurred. 350 * } 351 * @endcode 352 */ open(const protocol_type & protocol,boost::system::error_code & ec)353 BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol, 354 boost::system::error_code& ec) 355 { 356 this->get_service().open(this->get_implementation(), protocol, ec); 357 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 358 } 359 360 /// Assign an existing native socket to the socket. 361 /* 362 * This function opens the socket to hold an existing native socket. 363 * 364 * @param protocol An object specifying which protocol is to be used. 365 * 366 * @param native_socket A native socket. 367 * 368 * @throws boost::system::system_error Thrown on failure. 369 */ assign(const protocol_type & protocol,const native_handle_type & native_socket)370 void assign(const protocol_type& protocol, 371 const native_handle_type& native_socket) 372 { 373 boost::system::error_code ec; 374 this->get_service().assign(this->get_implementation(), 375 protocol, native_socket, ec); 376 boost::asio::detail::throw_error(ec, "assign"); 377 } 378 379 /// Assign an existing native socket to the socket. 380 /* 381 * This function opens the socket to hold an existing native socket. 382 * 383 * @param protocol An object specifying which protocol is to be used. 384 * 385 * @param native_socket A native socket. 386 * 387 * @param ec Set to indicate what error occurred, if any. 388 */ assign(const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)389 BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol, 390 const native_handle_type& native_socket, boost::system::error_code& ec) 391 { 392 this->get_service().assign(this->get_implementation(), 393 protocol, native_socket, ec); 394 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 395 } 396 397 /// Determine whether the socket is open. is_open() const398 bool is_open() const 399 { 400 return this->get_service().is_open(this->get_implementation()); 401 } 402 403 /// Close the socket. 404 /** 405 * This function is used to close the socket. Any asynchronous send, receive 406 * or connect operations will be cancelled immediately, and will complete 407 * with the boost::asio::error::operation_aborted error. 408 * 409 * @throws boost::system::system_error Thrown on failure. Note that, even if 410 * the function indicates an error, the underlying descriptor is closed. 411 * 412 * @note For portable behaviour with respect to graceful closure of a 413 * connected socket, call shutdown() before closing the socket. 414 */ close()415 void close() 416 { 417 boost::system::error_code ec; 418 this->get_service().close(this->get_implementation(), ec); 419 boost::asio::detail::throw_error(ec, "close"); 420 } 421 422 /// Close the socket. 423 /** 424 * This function is used to close the socket. Any asynchronous send, receive 425 * or connect operations will be cancelled immediately, and will complete 426 * with the boost::asio::error::operation_aborted error. 427 * 428 * @param ec Set to indicate what error occurred, if any. Note that, even if 429 * the function indicates an error, the underlying descriptor is closed. 430 * 431 * @par Example 432 * @code 433 * boost::asio::ip::tcp::socket socket(io_context); 434 * ... 435 * boost::system::error_code ec; 436 * socket.close(ec); 437 * if (ec) 438 * { 439 * // An error occurred. 440 * } 441 * @endcode 442 * 443 * @note For portable behaviour with respect to graceful closure of a 444 * connected socket, call shutdown() before closing the socket. 445 */ close(boost::system::error_code & ec)446 BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec) 447 { 448 this->get_service().close(this->get_implementation(), ec); 449 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 450 } 451 452 /// Release ownership of the underlying native socket. 453 /** 454 * This function causes all outstanding asynchronous connect, send and receive 455 * operations to finish immediately, and the handlers for cancelled operations 456 * will be passed the boost::asio::error::operation_aborted error. Ownership 457 * of the native socket is then transferred to the caller. 458 * 459 * @throws boost::system::system_error Thrown on failure. 460 * 461 * @note This function is unsupported on Windows versions prior to Windows 462 * 8.1, and will fail with boost::asio::error::operation_not_supported on 463 * these platforms. 464 */ 465 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 466 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 467 __declspec(deprecated("This function always fails with " 468 "operation_not_supported when used on Windows versions " 469 "prior to Windows 8.1.")) 470 #endif release()471 native_handle_type release() 472 { 473 boost::system::error_code ec; 474 native_handle_type s = this->get_service().release( 475 this->get_implementation(), ec); 476 boost::asio::detail::throw_error(ec, "release"); 477 return s; 478 } 479 480 /// Release ownership of the underlying native socket. 481 /** 482 * This function causes all outstanding asynchronous connect, send and receive 483 * operations to finish immediately, and the handlers for cancelled operations 484 * will be passed the boost::asio::error::operation_aborted error. Ownership 485 * of the native socket is then transferred to the caller. 486 * 487 * @param ec Set to indicate what error occurred, if any. 488 * 489 * @note This function is unsupported on Windows versions prior to Windows 490 * 8.1, and will fail with boost::asio::error::operation_not_supported on 491 * these platforms. 492 */ 493 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 494 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) 495 __declspec(deprecated("This function always fails with " 496 "operation_not_supported when used on Windows versions " 497 "prior to Windows 8.1.")) 498 #endif release(boost::system::error_code & ec)499 native_handle_type release(boost::system::error_code& ec) 500 { 501 return this->get_service().release(this->get_implementation(), ec); 502 } 503 504 /// Get the native socket representation. 505 /** 506 * This function may be used to obtain the underlying representation of the 507 * socket. This is intended to allow access to native socket functionality 508 * that is not otherwise provided. 509 */ native_handle()510 native_handle_type native_handle() 511 { 512 return this->get_service().native_handle(this->get_implementation()); 513 } 514 515 /// Cancel all asynchronous operations associated with the socket. 516 /** 517 * This function causes all outstanding asynchronous connect, send and receive 518 * operations to finish immediately, and the handlers for cancelled operations 519 * will be passed the boost::asio::error::operation_aborted error. 520 * 521 * @throws boost::system::system_error Thrown on failure. 522 * 523 * @note Calls to cancel() will always fail with 524 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 525 * Server 2003, and earlier versions of Windows, unless 526 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 527 * two issues that should be considered before enabling its use: 528 * 529 * @li It will only cancel asynchronous operations that were initiated in the 530 * current thread. 531 * 532 * @li It can appear to complete without error, but the request to cancel the 533 * unfinished operations may be silently ignored by the operating system. 534 * Whether it works or not seems to depend on the drivers that are installed. 535 * 536 * For portable cancellation, consider using one of the following 537 * alternatives: 538 * 539 * @li Disable asio's I/O completion port backend by defining 540 * BOOST_ASIO_DISABLE_IOCP. 541 * 542 * @li Use the close() function to simultaneously cancel the outstanding 543 * operations and close the socket. 544 * 545 * When running on Windows Vista, Windows Server 2008, and later, the 546 * CancelIoEx function is always used. This function does not have the 547 * problems described above. 548 */ 549 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 550 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 551 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 552 __declspec(deprecated("By default, this function always fails with " 553 "operation_not_supported when used on Windows XP, Windows Server 2003, " 554 "or earlier. Consult documentation for details.")) 555 #endif cancel()556 void cancel() 557 { 558 boost::system::error_code ec; 559 this->get_service().cancel(this->get_implementation(), ec); 560 boost::asio::detail::throw_error(ec, "cancel"); 561 } 562 563 /// Cancel all asynchronous operations associated with the socket. 564 /** 565 * This function causes all outstanding asynchronous connect, send and receive 566 * operations to finish immediately, and the handlers for cancelled operations 567 * will be passed the boost::asio::error::operation_aborted error. 568 * 569 * @param ec Set to indicate what error occurred, if any. 570 * 571 * @note Calls to cancel() will always fail with 572 * boost::asio::error::operation_not_supported when run on Windows XP, Windows 573 * Server 2003, and earlier versions of Windows, unless 574 * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has 575 * two issues that should be considered before enabling its use: 576 * 577 * @li It will only cancel asynchronous operations that were initiated in the 578 * current thread. 579 * 580 * @li It can appear to complete without error, but the request to cancel the 581 * unfinished operations may be silently ignored by the operating system. 582 * Whether it works or not seems to depend on the drivers that are installed. 583 * 584 * For portable cancellation, consider using one of the following 585 * alternatives: 586 * 587 * @li Disable asio's I/O completion port backend by defining 588 * BOOST_ASIO_DISABLE_IOCP. 589 * 590 * @li Use the close() function to simultaneously cancel the outstanding 591 * operations and close the socket. 592 * 593 * When running on Windows Vista, Windows Server 2008, and later, the 594 * CancelIoEx function is always used. This function does not have the 595 * problems described above. 596 */ 597 #if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ 598 && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ 599 && !defined(BOOST_ASIO_ENABLE_CANCELIO) 600 __declspec(deprecated("By default, this function always fails with " 601 "operation_not_supported when used on Windows XP, Windows Server 2003, " 602 "or earlier. Consult documentation for details.")) 603 #endif cancel(boost::system::error_code & ec)604 BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec) 605 { 606 this->get_service().cancel(this->get_implementation(), ec); 607 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 608 } 609 610 /// Determine whether the socket is at the out-of-band data mark. 611 /** 612 * This function is used to check whether the socket input is currently 613 * positioned at the out-of-band data mark. 614 * 615 * @return A bool indicating whether the socket is at the out-of-band data 616 * mark. 617 * 618 * @throws boost::system::system_error Thrown on failure. 619 */ at_mark() const620 bool at_mark() const 621 { 622 boost::system::error_code ec; 623 bool b = this->get_service().at_mark(this->get_implementation(), ec); 624 boost::asio::detail::throw_error(ec, "at_mark"); 625 return b; 626 } 627 628 /// Determine whether the socket is at the out-of-band data mark. 629 /** 630 * This function is used to check whether the socket input is currently 631 * positioned at the out-of-band data mark. 632 * 633 * @param ec Set to indicate what error occurred, if any. 634 * 635 * @return A bool indicating whether the socket is at the out-of-band data 636 * mark. 637 */ at_mark(boost::system::error_code & ec) const638 bool at_mark(boost::system::error_code& ec) const 639 { 640 return this->get_service().at_mark(this->get_implementation(), ec); 641 } 642 643 /// Determine the number of bytes available for reading. 644 /** 645 * This function is used to determine the number of bytes that may be read 646 * without blocking. 647 * 648 * @return The number of bytes that may be read without blocking, or 0 if an 649 * error occurs. 650 * 651 * @throws boost::system::system_error Thrown on failure. 652 */ available() const653 std::size_t available() const 654 { 655 boost::system::error_code ec; 656 std::size_t s = this->get_service().available( 657 this->get_implementation(), ec); 658 boost::asio::detail::throw_error(ec, "available"); 659 return s; 660 } 661 662 /// Determine the number of bytes available for reading. 663 /** 664 * This function is used to determine the number of bytes that may be read 665 * without blocking. 666 * 667 * @param ec Set to indicate what error occurred, if any. 668 * 669 * @return The number of bytes that may be read without blocking, or 0 if an 670 * error occurs. 671 */ available(boost::system::error_code & ec) const672 std::size_t available(boost::system::error_code& ec) const 673 { 674 return this->get_service().available(this->get_implementation(), ec); 675 } 676 677 /// Bind the socket to the given local endpoint. 678 /** 679 * This function binds the socket to the specified endpoint on the local 680 * machine. 681 * 682 * @param endpoint An endpoint on the local machine to which the socket will 683 * be bound. 684 * 685 * @throws boost::system::system_error Thrown on failure. 686 * 687 * @par Example 688 * @code 689 * boost::asio::ip::tcp::socket socket(io_context); 690 * socket.open(boost::asio::ip::tcp::v4()); 691 * socket.bind(boost::asio::ip::tcp::endpoint( 692 * boost::asio::ip::tcp::v4(), 12345)); 693 * @endcode 694 */ bind(const endpoint_type & endpoint)695 void bind(const endpoint_type& endpoint) 696 { 697 boost::system::error_code ec; 698 this->get_service().bind(this->get_implementation(), endpoint, ec); 699 boost::asio::detail::throw_error(ec, "bind"); 700 } 701 702 /// Bind the socket to the given local endpoint. 703 /** 704 * This function binds the socket to the specified endpoint on the local 705 * machine. 706 * 707 * @param endpoint An endpoint on the local machine to which the socket will 708 * be bound. 709 * 710 * @param ec Set to indicate what error occurred, if any. 711 * 712 * @par Example 713 * @code 714 * boost::asio::ip::tcp::socket socket(io_context); 715 * socket.open(boost::asio::ip::tcp::v4()); 716 * boost::system::error_code ec; 717 * socket.bind(boost::asio::ip::tcp::endpoint( 718 * boost::asio::ip::tcp::v4(), 12345), ec); 719 * if (ec) 720 * { 721 * // An error occurred. 722 * } 723 * @endcode 724 */ bind(const endpoint_type & endpoint,boost::system::error_code & ec)725 BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint, 726 boost::system::error_code& ec) 727 { 728 this->get_service().bind(this->get_implementation(), endpoint, ec); 729 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 730 } 731 732 /// Connect the socket to the specified endpoint. 733 /** 734 * This function is used to connect a socket to the specified remote endpoint. 735 * The function call will block until the connection is successfully made or 736 * an error occurs. 737 * 738 * The socket is automatically opened if it is not already open. If the 739 * connect fails, and the socket was automatically opened, the socket is 740 * not returned to the closed state. 741 * 742 * @param peer_endpoint The remote endpoint to which the socket will be 743 * connected. 744 * 745 * @throws boost::system::system_error Thrown on failure. 746 * 747 * @par Example 748 * @code 749 * boost::asio::ip::tcp::socket socket(io_context); 750 * boost::asio::ip::tcp::endpoint endpoint( 751 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 752 * socket.connect(endpoint); 753 * @endcode 754 */ connect(const endpoint_type & peer_endpoint)755 void connect(const endpoint_type& peer_endpoint) 756 { 757 boost::system::error_code ec; 758 if (!is_open()) 759 { 760 this->get_service().open(this->get_implementation(), 761 peer_endpoint.protocol(), ec); 762 boost::asio::detail::throw_error(ec, "connect"); 763 } 764 this->get_service().connect(this->get_implementation(), peer_endpoint, ec); 765 boost::asio::detail::throw_error(ec, "connect"); 766 } 767 768 /// Connect the socket to the specified endpoint. 769 /** 770 * This function is used to connect a socket to the specified remote endpoint. 771 * The function call will block until the connection is successfully made or 772 * an error occurs. 773 * 774 * The socket is automatically opened if it is not already open. If the 775 * connect fails, and the socket was automatically opened, the socket is 776 * not returned to the closed state. 777 * 778 * @param peer_endpoint The remote endpoint to which the socket will be 779 * connected. 780 * 781 * @param ec Set to indicate what error occurred, if any. 782 * 783 * @par Example 784 * @code 785 * boost::asio::ip::tcp::socket socket(io_context); 786 * boost::asio::ip::tcp::endpoint endpoint( 787 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 788 * boost::system::error_code ec; 789 * socket.connect(endpoint, ec); 790 * if (ec) 791 * { 792 * // An error occurred. 793 * } 794 * @endcode 795 */ connect(const endpoint_type & peer_endpoint,boost::system::error_code & ec)796 BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint, 797 boost::system::error_code& ec) 798 { 799 if (!is_open()) 800 { 801 this->get_service().open(this->get_implementation(), 802 peer_endpoint.protocol(), ec); 803 if (ec) 804 { 805 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 806 } 807 } 808 809 this->get_service().connect(this->get_implementation(), peer_endpoint, ec); 810 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 811 } 812 813 /// Start an asynchronous connect. 814 /** 815 * This function is used to asynchronously connect a socket to the specified 816 * remote endpoint. The function call always returns immediately. 817 * 818 * The socket is automatically opened if it is not already open. If the 819 * connect fails, and the socket was automatically opened, the socket is 820 * not returned to the closed state. 821 * 822 * @param peer_endpoint The remote endpoint to which the socket will be 823 * connected. Copies will be made of the endpoint object as required. 824 * 825 * @param handler The handler to be called when the connection operation 826 * completes. Copies will be made of the handler as required. The function 827 * signature of the handler must be: 828 * @code void handler( 829 * const boost::system::error_code& error // Result of operation 830 * ); @endcode 831 * Regardless of whether the asynchronous operation completes immediately or 832 * not, the handler will not be invoked from within this function. Invocation 833 * of the handler will be performed in a manner equivalent to using 834 * boost::asio::io_context::post(). 835 * 836 * @par Example 837 * @code 838 * void connect_handler(const boost::system::error_code& error) 839 * { 840 * if (!error) 841 * { 842 * // Connect succeeded. 843 * } 844 * } 845 * 846 * ... 847 * 848 * boost::asio::ip::tcp::socket socket(io_context); 849 * boost::asio::ip::tcp::endpoint endpoint( 850 * boost::asio::ip::address::from_string("1.2.3.4"), 12345); 851 * socket.async_connect(endpoint, connect_handler); 852 * @endcode 853 */ 854 template <typename ConnectHandler> BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,void (boost::system::error_code))855 BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, 856 void (boost::system::error_code)) 857 async_connect(const endpoint_type& peer_endpoint, 858 BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) 859 { 860 // If you get an error on the following line it means that your handler does 861 // not meet the documented type requirements for a ConnectHandler. 862 BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; 863 864 if (!is_open()) 865 { 866 boost::system::error_code ec; 867 const protocol_type protocol = peer_endpoint.protocol(); 868 this->get_service().open(this->get_implementation(), protocol, ec); 869 if (ec) 870 { 871 async_completion<ConnectHandler, 872 void (boost::system::error_code)> init(handler); 873 874 boost::asio::post(this->get_executor(), 875 boost::asio::detail::bind_handler( 876 BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE( 877 ConnectHandler, void (boost::system::error_code)))( 878 init.completion_handler), ec)); 879 880 return init.result.get(); 881 } 882 } 883 884 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 885 return this->get_service().async_connect(this->get_implementation(), 886 peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); 887 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 888 async_completion<ConnectHandler, 889 void (boost::system::error_code)> init(handler); 890 891 this->get_service().async_connect( 892 this->get_implementation(), peer_endpoint, init.completion_handler); 893 894 return init.result.get(); 895 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 896 } 897 898 /// Set an option on the socket. 899 /** 900 * This function is used to set an option on the socket. 901 * 902 * @param option The new option value to be set on the socket. 903 * 904 * @throws boost::system::system_error Thrown on failure. 905 * 906 * @sa SettableSocketOption @n 907 * boost::asio::socket_base::broadcast @n 908 * boost::asio::socket_base::do_not_route @n 909 * boost::asio::socket_base::keep_alive @n 910 * boost::asio::socket_base::linger @n 911 * boost::asio::socket_base::receive_buffer_size @n 912 * boost::asio::socket_base::receive_low_watermark @n 913 * boost::asio::socket_base::reuse_address @n 914 * boost::asio::socket_base::send_buffer_size @n 915 * boost::asio::socket_base::send_low_watermark @n 916 * boost::asio::ip::multicast::join_group @n 917 * boost::asio::ip::multicast::leave_group @n 918 * boost::asio::ip::multicast::enable_loopback @n 919 * boost::asio::ip::multicast::outbound_interface @n 920 * boost::asio::ip::multicast::hops @n 921 * boost::asio::ip::tcp::no_delay 922 * 923 * @par Example 924 * Setting the IPPROTO_TCP/TCP_NODELAY option: 925 * @code 926 * boost::asio::ip::tcp::socket socket(io_context); 927 * ... 928 * boost::asio::ip::tcp::no_delay option(true); 929 * socket.set_option(option); 930 * @endcode 931 */ 932 template <typename SettableSocketOption> set_option(const SettableSocketOption & option)933 void set_option(const SettableSocketOption& option) 934 { 935 boost::system::error_code ec; 936 this->get_service().set_option(this->get_implementation(), option, ec); 937 boost::asio::detail::throw_error(ec, "set_option"); 938 } 939 940 /// Set an option on the socket. 941 /** 942 * This function is used to set an option on the socket. 943 * 944 * @param option The new option value to be set on the socket. 945 * 946 * @param ec Set to indicate what error occurred, if any. 947 * 948 * @sa SettableSocketOption @n 949 * boost::asio::socket_base::broadcast @n 950 * boost::asio::socket_base::do_not_route @n 951 * boost::asio::socket_base::keep_alive @n 952 * boost::asio::socket_base::linger @n 953 * boost::asio::socket_base::receive_buffer_size @n 954 * boost::asio::socket_base::receive_low_watermark @n 955 * boost::asio::socket_base::reuse_address @n 956 * boost::asio::socket_base::send_buffer_size @n 957 * boost::asio::socket_base::send_low_watermark @n 958 * boost::asio::ip::multicast::join_group @n 959 * boost::asio::ip::multicast::leave_group @n 960 * boost::asio::ip::multicast::enable_loopback @n 961 * boost::asio::ip::multicast::outbound_interface @n 962 * boost::asio::ip::multicast::hops @n 963 * boost::asio::ip::tcp::no_delay 964 * 965 * @par Example 966 * Setting the IPPROTO_TCP/TCP_NODELAY option: 967 * @code 968 * boost::asio::ip::tcp::socket socket(io_context); 969 * ... 970 * boost::asio::ip::tcp::no_delay option(true); 971 * boost::system::error_code ec; 972 * socket.set_option(option, ec); 973 * if (ec) 974 * { 975 * // An error occurred. 976 * } 977 * @endcode 978 */ 979 template <typename SettableSocketOption> set_option(const SettableSocketOption & option,boost::system::error_code & ec)980 BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option, 981 boost::system::error_code& ec) 982 { 983 this->get_service().set_option(this->get_implementation(), option, ec); 984 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 985 } 986 987 /// Get an option from the socket. 988 /** 989 * This function is used to get the current value of an option on the socket. 990 * 991 * @param option The option value to be obtained from the socket. 992 * 993 * @throws boost::system::system_error Thrown on failure. 994 * 995 * @sa GettableSocketOption @n 996 * boost::asio::socket_base::broadcast @n 997 * boost::asio::socket_base::do_not_route @n 998 * boost::asio::socket_base::keep_alive @n 999 * boost::asio::socket_base::linger @n 1000 * boost::asio::socket_base::receive_buffer_size @n 1001 * boost::asio::socket_base::receive_low_watermark @n 1002 * boost::asio::socket_base::reuse_address @n 1003 * boost::asio::socket_base::send_buffer_size @n 1004 * boost::asio::socket_base::send_low_watermark @n 1005 * boost::asio::ip::multicast::join_group @n 1006 * boost::asio::ip::multicast::leave_group @n 1007 * boost::asio::ip::multicast::enable_loopback @n 1008 * boost::asio::ip::multicast::outbound_interface @n 1009 * boost::asio::ip::multicast::hops @n 1010 * boost::asio::ip::tcp::no_delay 1011 * 1012 * @par Example 1013 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1014 * @code 1015 * boost::asio::ip::tcp::socket socket(io_context); 1016 * ... 1017 * boost::asio::ip::tcp::socket::keep_alive option; 1018 * socket.get_option(option); 1019 * bool is_set = option.value(); 1020 * @endcode 1021 */ 1022 template <typename GettableSocketOption> get_option(GettableSocketOption & option) const1023 void get_option(GettableSocketOption& option) const 1024 { 1025 boost::system::error_code ec; 1026 this->get_service().get_option(this->get_implementation(), option, ec); 1027 boost::asio::detail::throw_error(ec, "get_option"); 1028 } 1029 1030 /// Get an option from the socket. 1031 /** 1032 * This function is used to get the current value of an option on the socket. 1033 * 1034 * @param option The option value to be obtained from the socket. 1035 * 1036 * @param ec Set to indicate what error occurred, if any. 1037 * 1038 * @sa GettableSocketOption @n 1039 * boost::asio::socket_base::broadcast @n 1040 * boost::asio::socket_base::do_not_route @n 1041 * boost::asio::socket_base::keep_alive @n 1042 * boost::asio::socket_base::linger @n 1043 * boost::asio::socket_base::receive_buffer_size @n 1044 * boost::asio::socket_base::receive_low_watermark @n 1045 * boost::asio::socket_base::reuse_address @n 1046 * boost::asio::socket_base::send_buffer_size @n 1047 * boost::asio::socket_base::send_low_watermark @n 1048 * boost::asio::ip::multicast::join_group @n 1049 * boost::asio::ip::multicast::leave_group @n 1050 * boost::asio::ip::multicast::enable_loopback @n 1051 * boost::asio::ip::multicast::outbound_interface @n 1052 * boost::asio::ip::multicast::hops @n 1053 * boost::asio::ip::tcp::no_delay 1054 * 1055 * @par Example 1056 * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: 1057 * @code 1058 * boost::asio::ip::tcp::socket socket(io_context); 1059 * ... 1060 * boost::asio::ip::tcp::socket::keep_alive option; 1061 * boost::system::error_code ec; 1062 * socket.get_option(option, ec); 1063 * if (ec) 1064 * { 1065 * // An error occurred. 1066 * } 1067 * bool is_set = option.value(); 1068 * @endcode 1069 */ 1070 template <typename GettableSocketOption> get_option(GettableSocketOption & option,boost::system::error_code & ec) const1071 BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option, 1072 boost::system::error_code& ec) const 1073 { 1074 this->get_service().get_option(this->get_implementation(), option, ec); 1075 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1076 } 1077 1078 /// Perform an IO control command on the socket. 1079 /** 1080 * This function is used to execute an IO control command on the socket. 1081 * 1082 * @param command The IO control command to be performed on the socket. 1083 * 1084 * @throws boost::system::system_error Thrown on failure. 1085 * 1086 * @sa IoControlCommand @n 1087 * boost::asio::socket_base::bytes_readable @n 1088 * boost::asio::socket_base::non_blocking_io 1089 * 1090 * @par Example 1091 * Getting the number of bytes ready to read: 1092 * @code 1093 * boost::asio::ip::tcp::socket socket(io_context); 1094 * ... 1095 * boost::asio::ip::tcp::socket::bytes_readable command; 1096 * socket.io_control(command); 1097 * std::size_t bytes_readable = command.get(); 1098 * @endcode 1099 */ 1100 template <typename IoControlCommand> io_control(IoControlCommand & command)1101 void io_control(IoControlCommand& command) 1102 { 1103 boost::system::error_code ec; 1104 this->get_service().io_control(this->get_implementation(), command, ec); 1105 boost::asio::detail::throw_error(ec, "io_control"); 1106 } 1107 1108 /// Perform an IO control command on the socket. 1109 /** 1110 * This function is used to execute an IO control command on the socket. 1111 * 1112 * @param command The IO control command to be performed on the socket. 1113 * 1114 * @param ec Set to indicate what error occurred, if any. 1115 * 1116 * @sa IoControlCommand @n 1117 * boost::asio::socket_base::bytes_readable @n 1118 * boost::asio::socket_base::non_blocking_io 1119 * 1120 * @par Example 1121 * Getting the number of bytes ready to read: 1122 * @code 1123 * boost::asio::ip::tcp::socket socket(io_context); 1124 * ... 1125 * boost::asio::ip::tcp::socket::bytes_readable command; 1126 * boost::system::error_code ec; 1127 * socket.io_control(command, ec); 1128 * if (ec) 1129 * { 1130 * // An error occurred. 1131 * } 1132 * std::size_t bytes_readable = command.get(); 1133 * @endcode 1134 */ 1135 template <typename IoControlCommand> io_control(IoControlCommand & command,boost::system::error_code & ec)1136 BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command, 1137 boost::system::error_code& ec) 1138 { 1139 this->get_service().io_control(this->get_implementation(), command, ec); 1140 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1141 } 1142 1143 /// Gets the non-blocking mode of the socket. 1144 /** 1145 * @returns @c true if the socket's synchronous operations will fail with 1146 * boost::asio::error::would_block if they are unable to perform the requested 1147 * operation immediately. If @c false, synchronous operations will block 1148 * until complete. 1149 * 1150 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1151 * operations. Asynchronous operations will never fail with the error 1152 * boost::asio::error::would_block. 1153 */ non_blocking() const1154 bool non_blocking() const 1155 { 1156 return this->get_service().non_blocking(this->get_implementation()); 1157 } 1158 1159 /// Sets the non-blocking mode of the socket. 1160 /** 1161 * @param mode If @c true, the socket's synchronous operations will fail with 1162 * boost::asio::error::would_block if they are unable to perform the requested 1163 * operation immediately. If @c false, synchronous operations will block 1164 * until complete. 1165 * 1166 * @throws boost::system::system_error Thrown on failure. 1167 * 1168 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1169 * operations. Asynchronous operations will never fail with the error 1170 * boost::asio::error::would_block. 1171 */ non_blocking(bool mode)1172 void non_blocking(bool mode) 1173 { 1174 boost::system::error_code ec; 1175 this->get_service().non_blocking(this->get_implementation(), mode, ec); 1176 boost::asio::detail::throw_error(ec, "non_blocking"); 1177 } 1178 1179 /// Sets the non-blocking mode of the socket. 1180 /** 1181 * @param mode If @c true, the socket's synchronous operations will fail with 1182 * boost::asio::error::would_block if they are unable to perform the requested 1183 * operation immediately. If @c false, synchronous operations will block 1184 * until complete. 1185 * 1186 * @param ec Set to indicate what error occurred, if any. 1187 * 1188 * @note The non-blocking mode has no effect on the behaviour of asynchronous 1189 * operations. Asynchronous operations will never fail with the error 1190 * boost::asio::error::would_block. 1191 */ non_blocking(bool mode,boost::system::error_code & ec)1192 BOOST_ASIO_SYNC_OP_VOID non_blocking( 1193 bool mode, boost::system::error_code& ec) 1194 { 1195 this->get_service().non_blocking(this->get_implementation(), mode, ec); 1196 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1197 } 1198 1199 /// Gets the non-blocking mode of the native socket implementation. 1200 /** 1201 * This function is used to retrieve the non-blocking mode of the underlying 1202 * native socket. This mode has no effect on the behaviour of the socket 1203 * object's synchronous operations. 1204 * 1205 * @returns @c true if the underlying socket is in non-blocking mode and 1206 * direct system calls may fail with boost::asio::error::would_block (or the 1207 * equivalent system error). 1208 * 1209 * @note The current non-blocking mode is cached by the socket object. 1210 * Consequently, the return value may be incorrect if the non-blocking mode 1211 * was set directly on the native socket. 1212 * 1213 * @par Example 1214 * This function is intended to allow the encapsulation of arbitrary 1215 * non-blocking system calls as asynchronous operations, in a way that is 1216 * transparent to the user of the socket object. The following example 1217 * illustrates how Linux's @c sendfile system call might be encapsulated: 1218 * @code template <typename Handler> 1219 * struct sendfile_op 1220 * { 1221 * tcp::socket& sock_; 1222 * int fd_; 1223 * Handler handler_; 1224 * off_t offset_; 1225 * std::size_t total_bytes_transferred_; 1226 * 1227 * // Function call operator meeting WriteHandler requirements. 1228 * // Used as the handler for the async_write_some operation. 1229 * void operator()(boost::system::error_code ec, std::size_t) 1230 * { 1231 * // Put the underlying socket into non-blocking mode. 1232 * if (!ec) 1233 * if (!sock_.native_non_blocking()) 1234 * sock_.native_non_blocking(true, ec); 1235 * 1236 * if (!ec) 1237 * { 1238 * for (;;) 1239 * { 1240 * // Try the system call. 1241 * errno = 0; 1242 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1243 * ec = boost::system::error_code(n < 0 ? errno : 0, 1244 * boost::asio::error::get_system_category()); 1245 * total_bytes_transferred_ += ec ? 0 : n; 1246 * 1247 * // Retry operation immediately if interrupted by signal. 1248 * if (ec == boost::asio::error::interrupted) 1249 * continue; 1250 * 1251 * // Check if we need to run the operation again. 1252 * if (ec == boost::asio::error::would_block 1253 * || ec == boost::asio::error::try_again) 1254 * { 1255 * // We have to wait for the socket to become ready again. 1256 * sock_.async_wait(tcp::socket::wait_write, *this); 1257 * return; 1258 * } 1259 * 1260 * if (ec || n == 0) 1261 * { 1262 * // An error occurred, or we have reached the end of the file. 1263 * // Either way we must exit the loop so we can call the handler. 1264 * break; 1265 * } 1266 * 1267 * // Loop around to try calling sendfile again. 1268 * } 1269 * } 1270 * 1271 * // Pass result back to user's handler. 1272 * handler_(ec, total_bytes_transferred_); 1273 * } 1274 * }; 1275 * 1276 * template <typename Handler> 1277 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1278 * { 1279 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1280 * sock.async_wait(tcp::socket::wait_write, op); 1281 * } @endcode 1282 */ native_non_blocking() const1283 bool native_non_blocking() const 1284 { 1285 return this->get_service().native_non_blocking(this->get_implementation()); 1286 } 1287 1288 /// Sets the non-blocking mode of the native socket implementation. 1289 /** 1290 * This function is used to modify the non-blocking mode of the underlying 1291 * native socket. It has no effect on the behaviour of the socket object's 1292 * synchronous operations. 1293 * 1294 * @param mode If @c true, the underlying socket is put into non-blocking 1295 * mode and direct system calls may fail with boost::asio::error::would_block 1296 * (or the equivalent system error). 1297 * 1298 * @throws boost::system::system_error Thrown on failure. If the @c mode is 1299 * @c false, but the current value of @c non_blocking() is @c true, this 1300 * function fails with boost::asio::error::invalid_argument, as the 1301 * combination does not make sense. 1302 * 1303 * @par Example 1304 * This function is intended to allow the encapsulation of arbitrary 1305 * non-blocking system calls as asynchronous operations, in a way that is 1306 * transparent to the user of the socket object. The following example 1307 * illustrates how Linux's @c sendfile system call might be encapsulated: 1308 * @code template <typename Handler> 1309 * struct sendfile_op 1310 * { 1311 * tcp::socket& sock_; 1312 * int fd_; 1313 * Handler handler_; 1314 * off_t offset_; 1315 * std::size_t total_bytes_transferred_; 1316 * 1317 * // Function call operator meeting WriteHandler requirements. 1318 * // Used as the handler for the async_write_some operation. 1319 * void operator()(boost::system::error_code ec, std::size_t) 1320 * { 1321 * // Put the underlying socket into non-blocking mode. 1322 * if (!ec) 1323 * if (!sock_.native_non_blocking()) 1324 * sock_.native_non_blocking(true, ec); 1325 * 1326 * if (!ec) 1327 * { 1328 * for (;;) 1329 * { 1330 * // Try the system call. 1331 * errno = 0; 1332 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1333 * ec = boost::system::error_code(n < 0 ? errno : 0, 1334 * boost::asio::error::get_system_category()); 1335 * total_bytes_transferred_ += ec ? 0 : n; 1336 * 1337 * // Retry operation immediately if interrupted by signal. 1338 * if (ec == boost::asio::error::interrupted) 1339 * continue; 1340 * 1341 * // Check if we need to run the operation again. 1342 * if (ec == boost::asio::error::would_block 1343 * || ec == boost::asio::error::try_again) 1344 * { 1345 * // We have to wait for the socket to become ready again. 1346 * sock_.async_wait(tcp::socket::wait_write, *this); 1347 * return; 1348 * } 1349 * 1350 * if (ec || n == 0) 1351 * { 1352 * // An error occurred, or we have reached the end of the file. 1353 * // Either way we must exit the loop so we can call the handler. 1354 * break; 1355 * } 1356 * 1357 * // Loop around to try calling sendfile again. 1358 * } 1359 * } 1360 * 1361 * // Pass result back to user's handler. 1362 * handler_(ec, total_bytes_transferred_); 1363 * } 1364 * }; 1365 * 1366 * template <typename Handler> 1367 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1368 * { 1369 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1370 * sock.async_wait(tcp::socket::wait_write, op); 1371 * } @endcode 1372 */ native_non_blocking(bool mode)1373 void native_non_blocking(bool mode) 1374 { 1375 boost::system::error_code ec; 1376 this->get_service().native_non_blocking( 1377 this->get_implementation(), mode, ec); 1378 boost::asio::detail::throw_error(ec, "native_non_blocking"); 1379 } 1380 1381 /// Sets the non-blocking mode of the native socket implementation. 1382 /** 1383 * This function is used to modify the non-blocking mode of the underlying 1384 * native socket. It has no effect on the behaviour of the socket object's 1385 * synchronous operations. 1386 * 1387 * @param mode If @c true, the underlying socket is put into non-blocking 1388 * mode and direct system calls may fail with boost::asio::error::would_block 1389 * (or the equivalent system error). 1390 * 1391 * @param ec Set to indicate what error occurred, if any. If the @c mode is 1392 * @c false, but the current value of @c non_blocking() is @c true, this 1393 * function fails with boost::asio::error::invalid_argument, as the 1394 * combination does not make sense. 1395 * 1396 * @par Example 1397 * This function is intended to allow the encapsulation of arbitrary 1398 * non-blocking system calls as asynchronous operations, in a way that is 1399 * transparent to the user of the socket object. The following example 1400 * illustrates how Linux's @c sendfile system call might be encapsulated: 1401 * @code template <typename Handler> 1402 * struct sendfile_op 1403 * { 1404 * tcp::socket& sock_; 1405 * int fd_; 1406 * Handler handler_; 1407 * off_t offset_; 1408 * std::size_t total_bytes_transferred_; 1409 * 1410 * // Function call operator meeting WriteHandler requirements. 1411 * // Used as the handler for the async_write_some operation. 1412 * void operator()(boost::system::error_code ec, std::size_t) 1413 * { 1414 * // Put the underlying socket into non-blocking mode. 1415 * if (!ec) 1416 * if (!sock_.native_non_blocking()) 1417 * sock_.native_non_blocking(true, ec); 1418 * 1419 * if (!ec) 1420 * { 1421 * for (;;) 1422 * { 1423 * // Try the system call. 1424 * errno = 0; 1425 * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); 1426 * ec = boost::system::error_code(n < 0 ? errno : 0, 1427 * boost::asio::error::get_system_category()); 1428 * total_bytes_transferred_ += ec ? 0 : n; 1429 * 1430 * // Retry operation immediately if interrupted by signal. 1431 * if (ec == boost::asio::error::interrupted) 1432 * continue; 1433 * 1434 * // Check if we need to run the operation again. 1435 * if (ec == boost::asio::error::would_block 1436 * || ec == boost::asio::error::try_again) 1437 * { 1438 * // We have to wait for the socket to become ready again. 1439 * sock_.async_wait(tcp::socket::wait_write, *this); 1440 * return; 1441 * } 1442 * 1443 * if (ec || n == 0) 1444 * { 1445 * // An error occurred, or we have reached the end of the file. 1446 * // Either way we must exit the loop so we can call the handler. 1447 * break; 1448 * } 1449 * 1450 * // Loop around to try calling sendfile again. 1451 * } 1452 * } 1453 * 1454 * // Pass result back to user's handler. 1455 * handler_(ec, total_bytes_transferred_); 1456 * } 1457 * }; 1458 * 1459 * template <typename Handler> 1460 * void async_sendfile(tcp::socket& sock, int fd, Handler h) 1461 * { 1462 * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; 1463 * sock.async_wait(tcp::socket::wait_write, op); 1464 * } @endcode 1465 */ native_non_blocking(bool mode,boost::system::error_code & ec)1466 BOOST_ASIO_SYNC_OP_VOID native_non_blocking( 1467 bool mode, boost::system::error_code& ec) 1468 { 1469 this->get_service().native_non_blocking( 1470 this->get_implementation(), mode, ec); 1471 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1472 } 1473 1474 /// Get the local endpoint of the socket. 1475 /** 1476 * This function is used to obtain the locally bound endpoint of the socket. 1477 * 1478 * @returns An object that represents the local endpoint of the socket. 1479 * 1480 * @throws boost::system::system_error Thrown on failure. 1481 * 1482 * @par Example 1483 * @code 1484 * boost::asio::ip::tcp::socket socket(io_context); 1485 * ... 1486 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); 1487 * @endcode 1488 */ local_endpoint() const1489 endpoint_type local_endpoint() const 1490 { 1491 boost::system::error_code ec; 1492 endpoint_type ep = this->get_service().local_endpoint( 1493 this->get_implementation(), ec); 1494 boost::asio::detail::throw_error(ec, "local_endpoint"); 1495 return ep; 1496 } 1497 1498 /// Get the local endpoint of the socket. 1499 /** 1500 * This function is used to obtain the locally bound endpoint of the socket. 1501 * 1502 * @param ec Set to indicate what error occurred, if any. 1503 * 1504 * @returns An object that represents the local endpoint of the socket. 1505 * Returns a default-constructed endpoint object if an error occurred. 1506 * 1507 * @par Example 1508 * @code 1509 * boost::asio::ip::tcp::socket socket(io_context); 1510 * ... 1511 * boost::system::error_code ec; 1512 * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); 1513 * if (ec) 1514 * { 1515 * // An error occurred. 1516 * } 1517 * @endcode 1518 */ local_endpoint(boost::system::error_code & ec) const1519 endpoint_type local_endpoint(boost::system::error_code& ec) const 1520 { 1521 return this->get_service().local_endpoint(this->get_implementation(), ec); 1522 } 1523 1524 /// Get the remote endpoint of the socket. 1525 /** 1526 * This function is used to obtain the remote endpoint of the socket. 1527 * 1528 * @returns An object that represents the remote endpoint of the socket. 1529 * 1530 * @throws boost::system::system_error Thrown on failure. 1531 * 1532 * @par Example 1533 * @code 1534 * boost::asio::ip::tcp::socket socket(io_context); 1535 * ... 1536 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); 1537 * @endcode 1538 */ remote_endpoint() const1539 endpoint_type remote_endpoint() const 1540 { 1541 boost::system::error_code ec; 1542 endpoint_type ep = this->get_service().remote_endpoint( 1543 this->get_implementation(), ec); 1544 boost::asio::detail::throw_error(ec, "remote_endpoint"); 1545 return ep; 1546 } 1547 1548 /// Get the remote endpoint of the socket. 1549 /** 1550 * This function is used to obtain the remote endpoint of the socket. 1551 * 1552 * @param ec Set to indicate what error occurred, if any. 1553 * 1554 * @returns An object that represents the remote endpoint of the socket. 1555 * Returns a default-constructed endpoint object if an error occurred. 1556 * 1557 * @par Example 1558 * @code 1559 * boost::asio::ip::tcp::socket socket(io_context); 1560 * ... 1561 * boost::system::error_code ec; 1562 * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); 1563 * if (ec) 1564 * { 1565 * // An error occurred. 1566 * } 1567 * @endcode 1568 */ remote_endpoint(boost::system::error_code & ec) const1569 endpoint_type remote_endpoint(boost::system::error_code& ec) const 1570 { 1571 return this->get_service().remote_endpoint(this->get_implementation(), ec); 1572 } 1573 1574 /// Disable sends or receives on the socket. 1575 /** 1576 * This function is used to disable send operations, receive operations, or 1577 * both. 1578 * 1579 * @param what Determines what types of operation will no longer be allowed. 1580 * 1581 * @throws boost::system::system_error Thrown on failure. 1582 * 1583 * @par Example 1584 * Shutting down the send side of the socket: 1585 * @code 1586 * boost::asio::ip::tcp::socket socket(io_context); 1587 * ... 1588 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); 1589 * @endcode 1590 */ shutdown(shutdown_type what)1591 void shutdown(shutdown_type what) 1592 { 1593 boost::system::error_code ec; 1594 this->get_service().shutdown(this->get_implementation(), what, ec); 1595 boost::asio::detail::throw_error(ec, "shutdown"); 1596 } 1597 1598 /// Disable sends or receives on the socket. 1599 /** 1600 * This function is used to disable send operations, receive operations, or 1601 * both. 1602 * 1603 * @param what Determines what types of operation will no longer be allowed. 1604 * 1605 * @param ec Set to indicate what error occurred, if any. 1606 * 1607 * @par Example 1608 * Shutting down the send side of the socket: 1609 * @code 1610 * boost::asio::ip::tcp::socket socket(io_context); 1611 * ... 1612 * boost::system::error_code ec; 1613 * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); 1614 * if (ec) 1615 * { 1616 * // An error occurred. 1617 * } 1618 * @endcode 1619 */ shutdown(shutdown_type what,boost::system::error_code & ec)1620 BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what, 1621 boost::system::error_code& ec) 1622 { 1623 this->get_service().shutdown(this->get_implementation(), what, ec); 1624 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1625 } 1626 1627 /// Wait for the socket to become ready to read, ready to write, or to have 1628 /// pending error conditions. 1629 /** 1630 * This function is used to perform a blocking wait for a socket to enter 1631 * a ready to read, write or error condition state. 1632 * 1633 * @param w Specifies the desired socket state. 1634 * 1635 * @par Example 1636 * Waiting for a socket to become readable. 1637 * @code 1638 * boost::asio::ip::tcp::socket socket(io_context); 1639 * ... 1640 * socket.wait(boost::asio::ip::tcp::socket::wait_read); 1641 * @endcode 1642 */ wait(wait_type w)1643 void wait(wait_type w) 1644 { 1645 boost::system::error_code ec; 1646 this->get_service().wait(this->get_implementation(), w, ec); 1647 boost::asio::detail::throw_error(ec, "wait"); 1648 } 1649 1650 /// Wait for the socket to become ready to read, ready to write, or to have 1651 /// pending error conditions. 1652 /** 1653 * This function is used to perform a blocking wait for a socket to enter 1654 * a ready to read, write or error condition state. 1655 * 1656 * @param w Specifies the desired socket state. 1657 * 1658 * @param ec Set to indicate what error occurred, if any. 1659 * 1660 * @par Example 1661 * Waiting for a socket to become readable. 1662 * @code 1663 * boost::asio::ip::tcp::socket socket(io_context); 1664 * ... 1665 * boost::system::error_code ec; 1666 * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec); 1667 * @endcode 1668 */ wait(wait_type w,boost::system::error_code & ec)1669 BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec) 1670 { 1671 this->get_service().wait(this->get_implementation(), w, ec); 1672 BOOST_ASIO_SYNC_OP_VOID_RETURN(ec); 1673 } 1674 1675 /// Asynchronously wait for the socket to become ready to read, ready to 1676 /// write, or to have pending error conditions. 1677 /** 1678 * This function is used to perform an asynchronous wait for a socket to enter 1679 * a ready to read, write or error condition state. 1680 * 1681 * @param w Specifies the desired socket state. 1682 * 1683 * @param handler The handler to be called when the wait operation completes. 1684 * Copies will be made of the handler as required. The function signature of 1685 * the handler must be: 1686 * @code void handler( 1687 * const boost::system::error_code& error // Result of operation 1688 * ); @endcode 1689 * Regardless of whether the asynchronous operation completes immediately or 1690 * not, the handler will not be invoked from within this function. Invocation 1691 * of the handler will be performed in a manner equivalent to using 1692 * boost::asio::io_context::post(). 1693 * 1694 * @par Example 1695 * @code 1696 * void wait_handler(const boost::system::error_code& error) 1697 * { 1698 * if (!error) 1699 * { 1700 * // Wait succeeded. 1701 * } 1702 * } 1703 * 1704 * ... 1705 * 1706 * boost::asio::ip::tcp::socket socket(io_context); 1707 * ... 1708 * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler); 1709 * @endcode 1710 */ 1711 template <typename WaitHandler> BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,void (boost::system::error_code))1712 BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, 1713 void (boost::system::error_code)) 1714 async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler) 1715 { 1716 // If you get an error on the following line it means that your handler does 1717 // not meet the documented type requirements for a WaitHandler. 1718 BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; 1719 1720 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1721 return this->get_service().async_wait(this->get_implementation(), 1722 w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); 1723 #else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1724 async_completion<WaitHandler, 1725 void (boost::system::error_code)> init(handler); 1726 1727 this->get_service().async_wait(this->get_implementation(), 1728 w, init.completion_handler); 1729 1730 return init.result.get(); 1731 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1732 } 1733 1734 protected: 1735 /// Protected destructor to prevent deletion through this type. 1736 /** 1737 * This function destroys the socket, cancelling any outstanding asynchronous 1738 * operations associated with the socket as if by calling @c cancel. 1739 */ ~basic_socket()1740 ~basic_socket() 1741 { 1742 } 1743 1744 private: 1745 // Disallow copying and assignment. 1746 basic_socket(const basic_socket&) BOOST_ASIO_DELETED; 1747 basic_socket& operator=(const basic_socket&) BOOST_ASIO_DELETED; 1748 }; 1749 1750 } // namespace asio 1751 } // namespace boost 1752 1753 #include <boost/asio/detail/pop_options.hpp> 1754 1755 #if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1756 # undef BOOST_ASIO_SVC_T 1757 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES) 1758 1759 #endif // BOOST_ASIO_BASIC_SOCKET_HPP 1760