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

📄 win_iocp_socket_service.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
📖 第 1 页 / 共 5 页
字号:
  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }    // Copy buffers into WSABUF array.    ::WSABUF bufs[max_buffers];    typename MutableBufferSequence::const_iterator iter = buffers.begin();    typename MutableBufferSequence::const_iterator end = buffers.end();    DWORD i = 0;    size_t total_buffer_size = 0;    for (; iter != end && i < max_buffers; ++iter, ++i)    {      boost::asio::mutable_buffer buffer(*iter);      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);      total_buffer_size += boost::asio::buffer_size(buffer);    }    // A request to receive 0 bytes on a stream socket is a no-op.    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)    {      ec = boost::system::error_code();      return 0;    }    // Receive some data.    DWORD bytes_transferred = 0;    DWORD recv_flags = flags;    int result = ::WSARecv(impl.socket_, bufs, i,        &bytes_transferred, &recv_flags, 0, 0);    if (result != 0)    {      DWORD last_error = ::WSAGetLastError();      if (last_error == ERROR_NETNAME_DELETED)        last_error = WSAECONNRESET;      else if (last_error == ERROR_PORT_UNREACHABLE)        last_error = WSAECONNREFUSED;      ec = boost::system::error_code(last_error,          boost::asio::error::get_system_category());      return 0;    }    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)    {      ec = boost::asio::error::eof;      return 0;    }    ec = boost::system::error_code();    return bytes_transferred;  }  // Wait until data can be received without blocking.  size_t receive(implementation_type& impl, const null_buffers&,      socket_base::message_flags, boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }    // Wait for socket to become ready.    socket_ops::poll_read(impl.socket_, ec);    return 0;  }  template <typename MutableBufferSequence, typename Handler>  class receive_operation    : public operation  {  public:    receive_operation(int protocol_type, win_iocp_io_service& io_service,        weak_cancel_token_type cancel_token,        const MutableBufferSequence& buffers, Handler handler)      : operation(io_service,          &receive_operation<            MutableBufferSequence, Handler>::do_completion_impl,          &receive_operation<            MutableBufferSequence, Handler>::destroy_impl),        protocol_type_(protocol_type),        work_(io_service.get_io_service()),        cancel_token_(cancel_token),        buffers_(buffers),        handler_(handler)    {    }  private:    static void do_completion_impl(operation* op,        DWORD last_error, size_t bytes_transferred)    {      // Take ownership of the operation object.      typedef receive_operation<MutableBufferSequence, Handler> op_type;      op_type* handler_op(static_cast<op_type*>(op));      typedef handler_alloc_traits<Handler, op_type> alloc_traits;      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)      // Check whether buffers are still valid.      typename MutableBufferSequence::const_iterator iter        = handler_op->buffers_.begin();      typename MutableBufferSequence::const_iterator end        = handler_op->buffers_.end();      while (iter != end)      {        boost::asio::mutable_buffer buffer(*iter);        boost::asio::buffer_cast<char*>(buffer);        ++iter;      }#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)      // Map non-portable errors to their portable counterparts.      boost::system::error_code ec(last_error,          boost::asio::error::get_system_category());      if (ec.value() == ERROR_NETNAME_DELETED)      {        if (handler_op->cancel_token_.expired())          ec = boost::asio::error::operation_aborted;        else          ec = boost::asio::error::connection_reset;      }      else if (ec.value() == ERROR_PORT_UNREACHABLE)      {        ec = boost::asio::error::connection_refused;      }      // Check for connection closed.      else if (!ec && bytes_transferred == 0          && handler_op->protocol_type_ == SOCK_STREAM          && !boost::is_same<MutableBufferSequence, null_buffers>::value)      {        ec = boost::asio::error::eof;      }      // Make a copy of the handler so that the memory can be deallocated before      // the upcall is made.      Handler handler(handler_op->handler_);      // Free the memory associated with the handler.      ptr.reset();      // Call the handler.      boost_asio_handler_invoke_helpers::invoke(          detail::bind_handler(handler, ec, bytes_transferred), &handler);    }    static void destroy_impl(operation* op)    {      // Take ownership of the operation object.      typedef receive_operation<MutableBufferSequence, Handler> op_type;      op_type* handler_op(static_cast<op_type*>(op));      typedef handler_alloc_traits<Handler, op_type> alloc_traits;      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);      // A sub-object of the handler may be the true owner of the memory      // associated with the handler. Consequently, a local copy of the handler      // is required to ensure that any owning sub-object remains valid until      // after we have deallocated the memory here.      Handler handler(handler_op->handler_);      (void)handler;      // Free the memory associated with the handler.      ptr.reset();    }    int protocol_type_;    boost::asio::io_service::work work_;    weak_cancel_token_type cancel_token_;    MutableBufferSequence buffers_;    Handler handler_;  };  // Start an asynchronous receive. The buffer for the data being received  // must be valid for the lifetime of the asynchronous operation.  template <typename MutableBufferSequence, typename Handler>  void async_receive(implementation_type& impl,      const MutableBufferSequence& buffers,      socket_base::message_flags flags, Handler handler)  {    if (!is_open(impl))    {      this->get_io_service().post(bind_handler(handler,            boost::asio::error::bad_descriptor, 0));      return;    }#if defined(BOOST_ASIO_ENABLE_CANCELIO)    // Update the ID of the thread from which cancellation is safe.    if (impl.safe_cancellation_thread_id_ == 0)      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())      impl.safe_cancellation_thread_id_ = ~DWORD(0);#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)    // Allocate and construct an operation to wrap the handler.    typedef receive_operation<MutableBufferSequence, Handler> value_type;    typedef handler_alloc_traits<Handler, value_type> alloc_traits;    raw_handler_ptr<alloc_traits> raw_ptr(handler);    int protocol_type = impl.protocol_.type();    handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,        iocp_service_, impl.cancel_token_, buffers, handler);    // Copy buffers into WSABUF array.    ::WSABUF bufs[max_buffers];    typename MutableBufferSequence::const_iterator iter = buffers.begin();    typename MutableBufferSequence::const_iterator end = buffers.end();    DWORD i = 0;    size_t total_buffer_size = 0;    for (; iter != end && i < max_buffers; ++iter, ++i)    {      boost::asio::mutable_buffer buffer(*iter);      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);      total_buffer_size += boost::asio::buffer_size(buffer);    }    // A request to receive 0 bytes on a stream socket is a no-op.    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code error;      iocp_service_.post(bind_handler(handler, error, 0));      return;    }    // Receive some data.    DWORD bytes_transferred = 0;    DWORD recv_flags = flags;    int result = ::WSARecv(impl.socket_, bufs, i,        &bytes_transferred, &recv_flags, ptr.get(), 0);    DWORD last_error = ::WSAGetLastError();    if (result != 0 && last_error != WSA_IO_PENDING)    {      boost::asio::io_service::work work(this->get_io_service());      ptr.reset();      boost::system::error_code ec(last_error,          boost::asio::error::get_system_category());      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));    }    else    {      ptr.release();    }  }  // Wait until data can be received without blocking.  template <typename Handler>  void async_receive(implementation_type& impl, const null_buffers& buffers,      socket_base::message_flags flags, Handler handler)  {    if (!is_open(impl))    {      this->get_io_service().post(bind_handler(handler,            boost::asio::error::bad_descriptor, 0));    }    else if (impl.protocol_.type() == SOCK_STREAM)    {      // For stream sockets on Windows, we may issue a 0-byte overlapped      // WSARecv to wait until there is data available on the socket.#if defined(BOOST_ASIO_ENABLE_CANCELIO)      // Update the ID of the thread from which cancellation is safe.      if (impl.safe_cancellation_thread_id_ == 0)        impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();      else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())        impl.safe_cancellation_thread_id_ = ~DWORD(0);#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)      // Allocate and construct an operation to wrap the handler.      typedef receive_operation<null_buffers, Handler> value_type;      typedef handler_alloc_traits<Handler, value_type> alloc_traits;      raw_handler_ptr<alloc_traits> raw_ptr(handler);      int protocol_type = impl.protocol_.type();      handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,          iocp_service_, impl.cancel_token_, buffers, handler);      // Issue a receive operation with an empty buffer.      ::WSABUF buf = { 0, 0 };      DWORD bytes_transferred = 0;      DWORD recv_flags = flags;      int result = ::WSARecv(impl.socket_, &buf, 1,          &bytes_transferred, &recv_flags, ptr.get(), 0);      DWORD last_error = ::WSAGetLastError();      if (result != 0 && last_error != WSA_IO_PENDING)      {        boost::asio::io_service::work work(this->get_io_service());        ptr.reset();        boost::system::error_code ec(last_error,            boost::asio::error::get_system_category());        iocp_service_.post(bind_handler(handler, ec, bytes_transferred));      }      else      {        ptr.release();      }    }    else    {      // Check if the reactor was already obtained from the io_service.      reactor_type* reactor = static_cast<reactor_type*>(            interlocked_compare_exchange_pointer(              reinterpret_cast<void**>(&reactor_), 0, 0));      if (!reactor)      {        reactor = &(boost::asio::use_service<reactor_type>(              this->get_io_service()));        interlocked_exchange_pointer(            reinterpret_cast<void**>(&reactor_), reactor);      }      if (flags & socket_base::message_out_of_band)      {        reactor->start_except_op(impl.socket_, impl.reactor_data_,            null_buffers_operation<Handler>(this->get_io_service(), handler));      }      else      {        reactor->start_read_op(impl.socket_, impl.reactor_data_,            null_buffers_operation<Handler>(this->get_io_service(), handler),            false);      }    }  }  // Receive a datagram with the endpoint of the sender. Returns the number of  // bytes received.  template <typename MutableBufferSequence>  size_t receive_from(implementation_type& impl,      const MutableBufferSequence& buffers,      endpoint_type& sender_endpoint, socket_base::message_flags flags,      boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }    // Copy buffers into WSABUF array.    ::WSABUF bufs[max_buffers];    typename MutableBufferSequence::const_iterator iter = buffers.begin();    typename MutableBufferSequence::const_iterator end = buffers.end();    DWORD i = 0;    for (; iter != end && i < max_buffers; ++iter, ++i)    {      boost::asio::mutable_buffer buffer(*iter);      bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));      bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);    }    // Receive some data.    DWORD bytes_transferred = 0;    DWORD recv_flags = flags;    int endpoint_size = static_cast<int>(sender_endpoint.capacity());    int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,        &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);    if (result != 0)    {      DWORD last_error = ::WSAGetLastError();      if (last_error == ERROR_PORT_UNREACHABLE)        last_error = WSAECONNREFUSED;      ec = boost::system::error_code(last_error,          boost::asio::error::get_system_category());      return 0;    }    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)    {      ec = boost::asio::error::eof;      return 0;    }    sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));    ec = boost::system::error_code();    return bytes_transferred;  }  // Wait until data can be received without blocking.  size_t receive_from(implementation_type& impl,      const null_buffers&, endpoint_type& sender_endpoint,      socket_base::message_flags, boost::system::error_code& ec)  {    if (!is_open(impl))    {      ec = boost::asio::error::bad_descriptor;      return 0;    }    // Wait for socket to become ready.    socket_ops::poll_read(impl.socket_, ec);    // Reset endpoint since it can be given no sensible value at this time.    sender_endpoint = endpoint_type();

⌨️ 快捷键说明

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