boost::asio 错误“I/O 操作已中止...”

Posted

技术标签:

【中文标题】boost::asio 错误“I/O 操作已中止...”【英文标题】:boost::asio error "The I/O operation has been aborted..." 【发布时间】:2011-01-06 20:27:24 【问题描述】:

我收到此错误消息

“由于线程退出或应用程序请求,I/O 操作已中止”

当使用 boost::asio::socket::async_read_some()

错误是什么意思?我应该寻找什么?

以下是相关代码:

void tcp_connection::start()

  printf("Connected to simulator\n");

  socket_.async_read_some(boost::asio::buffer(myBuffer,256),
      boost::bind(&tcp_connection::read_sim_handler,this,
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));


void tcp_connection::read_sim_handler(
                                  const boost::system::error_code& error, // Result of operation.
                                  std::size_t len )         // Number of bytes read.

try 
if (error == boost::asio::error::eof) 
    // Connection closed cleanly by peer.
    printf("Sim connection closed\n");
    return;
 else if (error) 
    throw boost::system::system_error(error); // Some other error.  if( ! error ) 


socket_.async_read_some(boost::asio::buffer(myBuffer,256),
    boost::bind(&tcp_connection::read_sim_handler,this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));

 catch (std::exception& e)

std::cerr << e.what() << std::endl;


当我在 start() 方法中将 async_read_some() 调用替换为 read_some() 时,一切正常(除了服务器阻塞等待消息!)

在发表评论后,我看到 tcp_connection 超出范围。我从http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/tutorial/tutdaytime3.html复制了代码 它说: “我们将使用 shared_ptr 和 enable_shared_from_this 因为我们希望 tcp_connection 对象只要有引用它的操作就保持活动状态。” 我承认我不知道这一切意味着什么。所以我以某种方式破坏了它?

在进一步的cmets之后,答案是

void tcp_connection::start()

  printf("Connected to simulator\n");

  socket_.async_read_some(boost::asio::buffer(myBuffer,256),
      boost::bind(&tcp_connection::read_sim_handler,
              shared_from_this(),
      boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));

传递 shared_from_this() 而不是 this 使用了由服务器代码建立的聪明(太聪明?)保持活动基础设施,即使连接管理器不在范围内,通过正常方式。有关技术细节,请参阅接受答案下的 cmets。

【问题讨论】:

myBuffer 是 tcp_connection 的成员。 tcp_connection类由tcp_server代码创建,直接从boost.org/doc/libs/1_45_0/doc/html/boost_asio/tutorial/…复制而来 @villintehaspam 但是,我刚刚向 tcp_connection 添加了一个检测析构函数。它正在被调用!我认为你让我走上了正轨。 我现在更新了我的答案,因为我在 shared_ptr 和 enable_shared_from_this 上看到了您的附加文本。这些部分对于在示例中保持对象存活至关重要,请参阅我的答案。如果您需要更多说明,请对我的回答再写一条评论。 【参考方案1】:

您的 tcp_connection 对象或缓冲区对象可能在异步操作完成之前超出范围。

由于您的程序基于其中一个教程示例,您为什么不查看另一个读取一些数据的示例:http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp

您的课程超出范围的原因是您不再使用shared_from_this()。这样做是为您的类创建一个shared_ptr,该类由绑定处理程序存储。这意味着 shared_ptr 将使您的类保持活动状态,直到您的处理程序被调用。

这也是你需要从enable_shared_from_this继承的原因。

最后一个超出范围的shared_ptr 将删除您的类实例。

【讨论】:

我会接受这个答案。当我将连接移出服务器并进入全局命名空间时,一切都开始工作了。丑陋,但可以使用。 如果你仔细看,你会发现我的代码是 tutdaytime3 和 async_tcp_echo_server 的组合 您可能还注意到异常被立即捕获 - 它不会通过调用堆栈传播到任何地方。 @ravenspoint,如果您再看一下示例,您会发现自动变量实际上不是连接对象,而是连接对象的 shared_ptr。这是一个很大的区别 - 只有 shared_ptr 超出范围,但由于您的连接类是引用计数的,因此您的连接对象保持活动状态。这是因为另一个 shared_ptr 是由 shared_from_this() 创建的。 @ravenspoint,因为它在您发布的代码中这么说?在对 _socket.async_read_some(...) 的所有调用中,您将需要使用 shared_from_this() 而不是 this,否则您的对象将超出范围。示例中的生命周期如下: 1. 在 server::start_accept 方法中创建并存储在 shared_ptr 中。 2. 使用 shared_ptr 绑定到 handle_accept 方法。 3. start_accept 方法结束,第一个 shared_ptr 超出范围。 4. handle_accept 被调用,这个调用从它从 shared_ptr 获得的连接开始......继续。

以上是关于boost::asio 错误“I/O 操作已中止...”的主要内容,如果未能解决你的问题,请参考以下文章

boost/asio/ssl 抛出“未定义的引用”错误

使用 boost::asio::spawn 生成的 asio 处理程序中的 boost::property_tree::read_xml 段错误

是啥导致了 boost C++ asio 中的 asio.misc.3 错误

boost asio 学习 错误处理

BOOST中read_some和 boost::asio::error::eof错误

“xtime: ambiguous symbol”错误,包括 <boost/asio.hpp> [关闭]