Boost C++ 库

……是世界上最受推崇、设计最精巧的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ Coding Standards

basic_socket::native_non_blocking (3 个重载之一) - Boost C++ 函数库
PrevUpHomeNext

获取本机套接字实现的非阻塞模式。

bool native_non_blocking() const;

此函数用于检索底层原生套接字的非阻塞模式。此模式对套接字对象的同步操作的行为没有影响。

返回值

true,如果底层套接字处于非阻塞模式,并且直接的系统调用可能会因 boost::asio::error::would_block(或等效的系统错误)而失败。

备注

当前的非阻塞模式由套接字对象缓存。因此,如果非阻塞模式直接在原生套接字上设置,则返回值可能不正确。

示例

此函数旨在允许将任意非阻塞系统调用封装为异步操作,并且对套接字对象的用户来说是透明的。以下示例说明了如何封装 Linux 的 sendfile 系统调用。

template <typename Handler>
struct sendfile_op
{
  tcp::socket& sock_;
  int fd_;
  Handler handler_;
  off_t offset_;
  std::size_t total_bytes_transferred_;

  // Function call operator meeting WriteHandler requirements.
  // Used as the handler for the async_write_some operation.
  void operator()(boost::system::error_code ec, std::size_t)
  {
    // Put the underlying socket into non-blocking mode.
    if (!ec)
      if (!sock_.native_non_blocking())
        sock_.native_non_blocking(true, ec);

    if (!ec)
    {
      for (;;)
      {
        // Try the system call.
        errno = 0;
        int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
        ec = boost::system::error_code(n < 0 ? errno : 0,
            boost::asio::error::get_system_category());
        total_bytes_transferred_ += ec ? 0 : n;

        // Retry operation immediately if interrupted by signal.
        if (ec == boost::asio::error::interrupted)
          continue;

        // Check if we need to run the operation again.
        if (ec == boost::asio::error::would_block
            || ec == boost::asio::error::try_again)
        {
          // We have to wait for the socket to become ready again.
          sock_.async_wait(tcp::socket::wait_write, *this);
          return;
        }

        if (ec || n == 0)
        {
          // An error occurred, or we have reached the end of the file.
          // Either way we must exit the loop so we can call the handler.
          break;
        }

        // Loop around to try calling sendfile again.
      }
    }

    // Pass result back to user's handler.
    handler_(ec, total_bytes_transferred_);
  }
};

template <typename Handler>
void async_sendfile(tcp::socket& sock, int fd, Handler h)
{
  sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
  sock.async_wait(tcp::socket::wait_write, op);
}

PrevUpHomeNext