c++ - boost Asio : checking socket ability to be readable/writable

标签 c++ sockets boost boost-asio

在我的应用程序中,我必须混合使用 asio 创建的套接字和 native 套接字(来自 C posgresql 库)。

我需要的是能够从特定套接字上的 boost 的 io_service 类实例中获取通知,使其处于非阻塞可读/可写状态,但不执行实际的读/写(将由第 3 方完成库),即有效地只做 select()/poll()

是否可以通过将 0 作为缓冲区长度传递给 async_read_some() 之类的函数来实现?

我做了一个快速测试,确实调用了缓冲区长度为零的 async_read_some() 确实调用了读取事件处理程序,但我不确定它是在 select< 中阻塞后完成的/strong>()/poll() 在相​​应的套接字句柄上,等待真正的“可以读取”状态。

最佳答案

这通常被称为 react 器式操作。

这些可以通过提供boost::asio::null_buffers获得到异步操作。 Reactor 风格的操作提供了一种在可以执行读取或写入操作时得到通知的方法,并且对于与第三方库集成、使用共享内存池等很有用。Boost.Asio documentation提供了一些信息和以下示例代码:

ip::tcp::socket socket(my_io_service);
...
socket.non_blocking(true);
...
socket.async_read_some(null_buffers(), read_handler);
...
void read_handler(boost::system::error_code ec)
{
  if (!ec)
  {
    std::vector<char> buf(socket.available());
    socket.read_some(buffer(buf));
  }
}

Boost.Asio 还提供了官方 nonblocking example ,说明了如何与想要直接在套接字上执行读写操作的库集成。


为操作提供一个零长度的缓冲区通常会导致空操作,因为操作的完成条件已经满足而无需尝试执行任何 I/O。这是一个完整的例子 demonstrating两者的区别:

#include <array>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

void print_status(
  const boost::system::error_code& error,
  std::size_t bytes_transferred,
  boost::asio::ip::tcp::socket& socket)
{
  std::cout << "error: " << error.message() << "; "
               "transferred: " << bytes_transferred << "; "
               "available: " << socket.available() << std::endl;
}

int main()
{
  using boost::asio::ip::tcp;

  // Create all I/O objects.
  boost::asio::io_service io_service;
  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
  tcp::socket socket1(io_service);
  tcp::socket socket2(io_service);

  // Connect the sockets.
  acceptor.async_accept(socket1, boost::bind(&noop));
  socket2.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
  io_service.run();
  io_service.reset();

  std::array<char, 512> buffer;

  // Reading into a zero-length buffer is a no-op and will be
  // considered immediately completed.
  socket1.async_receive(boost::asio::buffer(buffer, 0), 
    boost::bind(&print_status,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred,
      boost::ref(socket1))
  );
  // Guarantee the handler runs.
  assert(1 == io_service.poll());
  io_service.reset();

  // Start a reactor-style read operation by providing a null_buffer.
  socket1.async_receive(boost::asio::null_buffers(),
    boost::bind(&print_status,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred,
      boost::ref(socket1))
  );
  // Guarantee that the handler did not run.
  assert(0 == io_service.poll());
  // Write to the socket so that data becomes available.
  boost::asio::write(socket2, boost::asio::buffer("hello"));  
  assert(1 == io_service.poll());
}

输出:

error: Success; transferred: 0; available: 0
error: Success; transferred: 0; available: 6

关于c++ - boost Asio : checking socket ability to be readable/writable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33538529/

相关文章:

c++ - OpenGL Compute Shader 渲染到 3D 纹理似乎没有做任何事情

c++ - Cmake OpenCV 无法指定链接库

c - SSL_read 未接收

c++ - Boost Spirit x3 未编译

c++ - 如何在同一单位中使用具有比率的 Boost.Unit

c++ - 使用自定义时区将 boost::posix_time::ptime 转换为字符串

c++ - 如何从接口(interface)获取派生类?

c++ - 有没有办法将我的 GCL Lisp 文件与 Windows 上的单独 C++ 程序链接?

c - 关于UDP接收包时buffersize的问题

java - 从 Socket 多次打开读/写流