⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reactive_socket_service.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 4 页
字号:
//// reactive_socket_service.hpp// ~~~~~~~~~~~~~~~~~~~~~~~~~~~//// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)//// Distributed under the Boost Software License, Version 1.0. (See accompanying// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP#if defined(_MSC_VER) && (_MSC_VER >= 1200)# pragma once#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)#include <boost/asio/detail/push_options.hpp>#include <boost/asio/detail/push_options.hpp>#include <boost/shared_ptr.hpp>#include <boost/asio/detail/pop_options.hpp>#include <boost/asio/buffer.hpp>#include <boost/asio/error.hpp>#include <boost/asio/io_service.hpp>#include <boost/asio/socket_base.hpp>#include <boost/asio/detail/bind_handler.hpp>#include <boost/asio/detail/handler_base_from_member.hpp>#include <boost/asio/detail/noncopyable.hpp>#include <boost/asio/detail/service_base.hpp>#include <boost/asio/detail/socket_holder.hpp>#include <boost/asio/detail/socket_ops.hpp>#include <boost/asio/detail/socket_types.hpp>namespace boost {namespace asio {namespace detail {template <typename Protocol, typename Reactor>class reactive_socket_service  : public boost::asio::detail::service_base<      reactive_socket_service<Protocol, Reactor> >{public:  // The protocol type.  typedef Protocol protocol_type;  // The endpoint type.  typedef typename Protocol::endpoint endpoint_type;  // The native type of a socket.  typedef socket_type native_type;  // The implementation type of the socket.  class implementation_type    : private boost::asio::detail::noncopyable  {  public:    // Default constructor.    implementation_type()      : socket_(invalid_socket),        flags_(0),        protocol_(endpoint_type().protocol())    {    }  private:    // Only this service will have access to the internal values.    friend class reactive_socket_service<Protocol, Reactor>;    // The native socket representation.    socket_type socket_;    enum    {      // The user wants a non-blocking socket.      user_set_non_blocking = 1,      // The implementation wants a non-blocking socket (in order to be able to      // perform asynchronous read and write operations).      internal_non_blocking = 2,      // Helper "flag" used to determine whether the socket is non-blocking.      non_blocking = user_set_non_blocking | internal_non_blocking,      // User wants connection_aborted errors, which are disabled by default.      enable_connection_aborted = 4,      // The user set the linger option. Needs to be checked when closing.       user_set_linger = 8    };    // Flags indicating the current state of the socket.    unsigned char flags_;    // The protocol associated with the socket.    protocol_type protocol_;    // Per-descriptor data used by the reactor.    typename Reactor::per_descriptor_data reactor_data_;  };  // The maximum number of buffers to support in a single operation.  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };  // Constructor.  reactive_socket_service(boost::asio::io_service& io_service)    : boost::asio::detail::service_base<        reactive_socket_service<Protocol, Reactor> >(io_service),      reactor_(boost::asio::use_service<Reactor>(io_service))  {    reactor_.init_task();  }  // Destroy all user-defined handler objects owned by the service.  void shutdown_service()  {  }  // Construct a new socket implementation.  void construct(implementation_type& impl)  {    impl.socket_ = invalid_socket;    impl.flags_ = 0;  }  // Destroy a socket implementation.  void destroy(implementation_type& impl)  {    if (impl.socket_ != invalid_socket)    {      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);      if (impl.flags_ & implementation_type::non_blocking)      {        ioctl_arg_type non_blocking = 0;        boost::system::error_code ignored_ec;        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);        impl.flags_ &= ~implementation_type::non_blocking;      }      if (impl.flags_ & implementation_type::user_set_linger)      {        ::linger opt;        opt.l_onoff = 0;        opt.l_linger = 0;        boost::system::error_code ignored_ec;        socket_ops::setsockopt(impl.socket_,            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);      }      boost::system::error_code ignored_ec;      socket_ops::close(impl.socket_, ignored_ec);      impl.socket_ = invalid_socket;    }  }  // Open a new socket implementation.  boost::system::error_code open(implementation_type& impl,      const protocol_type& protocol, boost::system::error_code& ec)  {    if (is_open(impl))    {      ec = boost::asio::error::already_open;      return ec;    }    socket_holder sock(socket_ops::socket(protocol.family(),          protocol.type(), protocol.protocol(), ec));    if (sock.get() == invalid_socket)      return ec;    if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))    {      ec = boost::system::error_code(err,          boost::asio::error::get_system_category());      return ec;    }    impl.socket_ = sock.release();    impl.flags_ = 0;    impl.protocol_ = protocol;    ec = boost::system::error_code();    return ec;  }  // Assign a native socket to a socket implementation.  boost::system::error_code assign(implementation_type& impl,      const protocol_type& protocol, const native_type& native_socket,      boost::system::error_code& ec)  {    if (is_open(impl))    {      ec = boost::asio::error::already_open;      return ec;    }    if (int err = reactor_.register_descriptor(          native_socket, impl.reactor_data_))    {      ec = boost::system::error_code(err,          boost::asio::error::get_system_category());      return ec;    }    impl.socket_ = native_socket;    impl.flags_ = 0;    impl.protocol_ = protocol;    ec = boost::system::error_code();    return ec;  }  // Determine whether the socket is open.  bool is_open(const implementation_type& impl) const  {    return impl.socket_ != invalid_socket;  }  // Destroy a socket implementation.  boost::system::error_code close(implementation_type& impl,      boost::system::error_code& ec)  {    if (is_open(impl))    {      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);      if (impl.flags_ & implementation_type::non_blocking)      {        ioctl_arg_type non_blocking = 0;        boost::system::error_code ignored_ec;        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);        impl.flags_ &= ~implementation_type::non_blocking;      }      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)        return ec;      impl.socket_ = invalid_socket;    }    ec = boost::system::error_code();    return ec;  }  // Get the native socket representation.  native_type native(implementation_type& impl)  {    return impl.socket_;  }  // Cancel all operations associated with the socket.  boost::system::error_code cancel(implementation_type& impl,      boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    reactor_.cancel_ops(impl.socket_, impl.reactor_data_);    ec = boost::system::error_code();    return ec;  }  // Determine whether the socket is at the out-of-band data mark.  bool at_mark(const implementation_type& impl,      boost::system::error_code& ec) const  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return false;    }    boost::asio::detail::ioctl_arg_type value = 0;    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);#if defined(ENOTTY)    if (ec.value() == ENOTTY)      ec = boost::asio::error::not_socket;#endif // defined(ENOTTY)    return ec ? false : value != 0;  }  // Determine the number of bytes available for reading.  std::size_t available(const implementation_type& impl,      boost::system::error_code& ec) const  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }    boost::asio::detail::ioctl_arg_type value = 0;    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);#if defined(ENOTTY)    if (ec.value() == ENOTTY)      ec = boost::asio::error::not_socket;#endif // defined(ENOTTY)    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);  }  // Bind the socket to the specified local endpoint.  boost::system::error_code bind(implementation_type& impl,      const endpoint_type& endpoint, boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);    return ec;  }  // Place the socket into the state where it will listen for new connections.  boost::system::error_code listen(implementation_type& impl, int backlog,      boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    socket_ops::listen(impl.socket_, backlog, ec);    return ec;  }  // Set a socket option.  template <typename Option>  boost::system::error_code set_option(implementation_type& impl,      const Option& option, boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    if (option.level(impl.protocol_) == custom_socket_option_level        && option.name(impl.protocol_) == enable_connection_aborted_option)    {      if (option.size(impl.protocol_) != sizeof(int))      {        ec = boost::asio::error::invalid_argument;      }      else      {        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))          impl.flags_ |= implementation_type::enable_connection_aborted;        else          impl.flags_ &= ~implementation_type::enable_connection_aborted;        ec = boost::system::error_code();      }      return ec;    }    else    {      if (option.level(impl.protocol_) == SOL_SOCKET          && option.name(impl.protocol_) == SO_LINGER)      {        impl.flags_ |= implementation_type::user_set_linger;      }      socket_ops::setsockopt(impl.socket_,          option.level(impl.protocol_), option.name(impl.protocol_),          option.data(impl.protocol_), option.size(impl.protocol_), ec);#if defined(__MACH__) && defined(__APPLE__) \|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)      // To implement portable behaviour for SO_REUSEADDR with UDP sockets we      // need to also set SO_REUSEPORT on BSD-based platforms.      if (!ec && impl.protocol_.type() == SOCK_DGRAM          && option.level(impl.protocol_) == SOL_SOCKET          && option.name(impl.protocol_) == SO_REUSEADDR)      {        boost::system::error_code ignored_ec;        socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,            option.data(impl.protocol_), option.size(impl.protocol_),            ignored_ec);      }#endif      return ec;    }  }  // Set a socket option.  template <typename Option>  boost::system::error_code get_option(const implementation_type& impl,      Option& option, boost::system::error_code& ec) const  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    if (option.level(impl.protocol_) == custom_socket_option_level        && option.name(impl.protocol_) == enable_connection_aborted_option)    {      if (option.size(impl.protocol_) != sizeof(int))      {        ec = boost::asio::error::invalid_argument;      }      else      {        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));        if (impl.flags_ & implementation_type::enable_connection_aborted)          *target = 1;        else          *target = 0;        option.resize(impl.protocol_, sizeof(int));        ec = boost::system::error_code();      }      return ec;    }    else    {      size_t size = option.size(impl.protocol_);      socket_ops::getsockopt(impl.socket_,          option.level(impl.protocol_), option.name(impl.protocol_),          option.data(impl.protocol_), &size, ec);      if (!ec)        option.resize(impl.protocol_, size);      return ec;    }  }  // Perform an IO control command on the socket.  template <typename IO_Control_Command>  boost::system::error_code io_control(implementation_type& impl,      IO_Control_Command& command, boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return ec;    }    if (command.name() == static_cast<int>(FIONBIO))    {      // Flags are manipulated in a temporary variable so that the socket

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -