async_receive和async_send处理程序中的C++ Boost.Asio错误

NFR*_*RCR 2 c++ boost-asio

  1. 当error_code不为0时,连接是否正式"死"?

  2. 当error_code不为0时,读处理程序的bytesReceived参数是否可能是0以外的任何值?如果可能,那些字节是应该处理还是不处理?

Tan*_*ury 5

总之,非成功error_code并不能保证该连接是死的,而对于非组成的操作,例如async_receive(),bytes_transferred0以上的成功,始终0如果发生错误.


未成功error_code 并未正式表明连接已正式死亡.例如,在以下情况下,TCP连接仍然存在:

  • basic_stream_socket::async_receive()取消通过的未完成操作cancel()将导致处理程序被调用并出现boost::asio::error::operation_aborted错误.
  • 只有部分全双工连接shutdown().例如,如果套接字的接收端关闭,则仍然可以通过套接字通过连接发送数据.

对于非组合操作,当发生错误时,bytes_transferred将是0.但是,a 0并不表示发生了错误.例如,bytes_transferred可以0并且error_code可以在使用reactor样式操作或提供空缓冲区时指示成功.该async_receive()async_send()对文档StreamSocketService规定:

如果操作成功完成,则调用[handler]并传输字节数.否则调用它0.

另一方面,组合操作,例如boost::asio::async_read()可以用非成功error_code和非零调用bytes_transferred.例如,如果async_read()启动操作并在完成之前将其设置为读取1024个字节,则可以async_read_some()多次调用.如果接收到256个字节然后关闭连接,则async_read()处理程序将具有非零值error_code,bytes_transferred并指示缓冲区的256个字节有效.


这是一个完整的示例,演示即使某些操作失败也会保持连接:

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

void noop() {}

void print_status(
  const boost::system::error_code& error,
  std::size_t bytes_transferred)
{
  std::cout << "error = (" << error << ") " << error.message() << "; "
               "bytes_transferred = " << bytes_transferred
            << std::endl;
}

void run_io_service(std::string message, boost::asio::io_service& io_service)
{
  std::cout << message << ": ";
  io_service.run();
  io_service.reset();
}

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();

  const char data[] = "hello\n";
  char buffer[128];

  // Create an async receive operation and cancel it.
  socket1.async_receive(boost::asio::buffer(buffer), &print_status);
  socket1.cancel();
  run_io_service("async_receive1", io_service);

  // Create an async write operation.
  socket1.async_send(boost::asio::buffer(data), &print_status);
  run_io_service("async_send1", io_service);

  // Shutdown the receive side of the socket then create an async
  // receive operation.
  socket1.shutdown(tcp::socket::shutdown_receive);
  socket1.async_receive(boost::asio::buffer(buffer), &print_status);
  run_io_service("async_receive2", io_service);

  // Create an async write operation.
  socket1.async_send(boost::asio::buffer(data), &print_status);
  run_io_service("async_send2", io_service);
}
Run Code Online (Sandbox Code Playgroud)

输出:

async_receive1: error = (system:125) Operation canceled; bytes_transferred = 0
async_send1: error = (system:0) Success; bytes_transferred = 7
async_receive2: error = (asio.misc:2) End of file; bytes_transferred = 0
async_send2: error = (system:0) Success; bytes_transferred = 7
Run Code Online (Sandbox Code Playgroud)

  • @Dronz 谢谢。我的目的是让简短的答案具体针对问题中提出的_非组合_操作,如果发生错误,“bytes_transferred”将为“0”。对于非组合操作,情况并不总是如此。答案已更新,以强调差异并提供对文档的更多了解。 (2认同)