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

时间:2014-01-05 02:28:35

标签: c++ boost-asio

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

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

1 个答案:

答案 0 :(得分:5)

简而言之,不成功error_code并不保证连接已失效,对于非合成操作,此类async_receive()bytes_transferred将为0或更多关于成功的信息,如果发生错误,请始终0


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

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

对于非组合操作,当发生错误时,bytes_transferred将为0。但是,0并不表示发生了错误。例如,bytes_transferred可以是0error_code可以表示使用reactor-style operations或提供空缓冲区时的成功。 StreamSocketService州的async_receive()async_send()文档说明:

  

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

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


以下是一个完整的示例demonstrating即使某些操作失败也会保持连接:

#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);
}

输出:

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