中断boost::asio同步读取?

6
我正在使用asio同步套接字从后台线程读取TCP数据。这个过程被封装在一个"服务器"类中。
然而,我希望当这个类的析构函数被调用时,线程能够退出。 问题是调用任何读取函数都会导致阻塞,因此线程不能轻松地终止。 在Win32中有一个API:WaitForMultipleObjects,它可以实现我想要的效果。
那么,我该如何通过boost实现类似的效果呢?
5个回答

2
在我们的应用程序中,我们设置了“终止”条件,然后使用自连接到线程正在侦听的端口,以便它唤醒,注意到终止条件并终止。
你还可以检查boost实现-如果它们只在套接字上进行普通读取(即不使用类似WaitForMultipleObjects的东西来内部使用),那么您可能会得出结论,没有任何简单干净的方法来取消阻塞线程。如果他们正在等待多个对象(或完成端口),则可以深入挖掘,看看是否将唤醒阻塞线程的能力暴露给外部。
最后,您可以杀死线程-但是您必须离开boost来执行此操作,并了解后果,例如悬空或泄漏的资源。如果您正在关闭,则可能不需要考虑这一点,具体取决于该线程所做的其他事情。

2
我发现没有简单的方法来做到这一点。据说,有一些方法可以取消win32 IOCP,但在Windows XP上效果不佳。然而,微软已经为Windows Vista和7修复了这个问题。建议取消asio的async_read或async_write的方法是关闭套接字。
  • [析构函数]请注意我们想要拆除
  • [析构函数]关闭套接字
  • [析构函数]等待完成处理程序

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

  • [完成]立即返回。
如果您选择实现此操作,请小心。关闭套接字非常直接。然而,“等待完成处理程序”是一个巨大的低估。当服务器线程和其析构函数交互时,可能会出现几个微妙的角落情况和竞态条件。
这足够微妙,以至于我们构建了一个完成包装器(类似于io_service::strand),只是为了同步地取消所有挂起的完成回调。

1

最好的方法是创建一个socketpair(),(无论在boost::asio中是什么),将读取端添加到事件循环中,然后关闭写入端。您将立即被唤醒,并收到该套接字上的eof事件。

线程必须自愿关闭自己。

线程的生成者在其析构函数中应包含以下内容:

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

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

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


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接