中断boost :: asio同步读取?

时间:2009-12-06 23:10:47

标签: c++ multithreading boost network-programming boost-asio

我正在使用asio同步套接字从后台线程通过TCP读取数据。这封装在“服务器”类中。

但是,我希望线程在调用此类的析构函数时退出。 问题是对任何读取函数的调用都会阻塞,因此线程不能轻易终止。在Win32中有一个API:WaitForMultipleObjects,这将完全符合我的要求。

我如何通过提升获得类似效果?

5 个答案:

答案 0 :(得分:2)

在我们的应用程序中,我们设置“终止”条件,然后使用自身连接到线程正在侦听的端口,以便它被唤醒,注意终止条件并终止。

您还可以检查boost实现 - 如果它们只对套接字执行简单读取(即,不在内部使用WaitForMultipleObjects之类的东西),那么您可能会得出结论,没有任何东西可以简单而干净地解除阻塞线。如果他们在等待多个对象(或完成端口),你可以四处寻找唤醒阻塞线程的能力是否暴露在外面。

最后,你可以杀死线程 - 但你必须超越提升才能做到这一点,并了解后果,例如悬空或泄漏的资源。如果你正在关闭,这可能不是一个问题,取决于该线程正在做什么。

答案 1 :(得分:2)

我发现没有简单的方法可以做到这一点。据说,有办法取消win32 IOCP,但它在Windows XP上运行不佳。 MS确实为Windows Vista和7修复了它。取消asio async_readasync_write的推荐方法是关闭套接字。

  • [析构者]请注意我们要拆解
  • [析构函数]关闭套接字
  • [析构函数]等待完成处理程序

  • [完成]如果拆除并且我们因为套接字关闭而失败,通知析构函数完成处理程序已完成。

  • [完成]立即返回。

如果您选择实施此操作,请务必小心。关闭套接字非常简单。 “等待完成处理程序”然而却是巨大的不足。当服务器的线程及其析构函数交互时,可能会出现一些微妙的角落情况和竞争条件。

这非常微妙,我们构建了一个完成包装器(类似于io_service::strand,只是为了同步取消所有挂起的完成回调。

答案 2 :(得分:1)

最好的方法是创建一个socketpair(),(boost::asio用语中的任何内容),将读取器端添加到事件循环中,然后关闭编写器端。你会立刻被那个插座上的eof事件唤醒。

然后线程必须自动关闭。

线程的产生者应该在其析构函数中具有以下内容:

~object()
{
    shutdown_queue.shutdown();   // ask thread to shut down
    thread.join();               // wait until it does
}

答案 3 :(得分:0)

boost::system::error_code _error_code;
client_socket_->shutdown(client_socket_->shutdown_both, _error_code);

以上代码可帮助我立即关闭同步读取。

答案 4 :(得分:-1)

使用socket.cancel();结束在套接字上阻塞的所有当前异步操作。客户端套接字可能需要在循环中被杀死。我从来没有以这种方式关闭服务器,但你可以使用shared_from_this()并在循环中运行cancel()/ close(),类似于boost聊天示例async_writes到所有客户端的方式。