6

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

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

我如何通过 boost 达到类似的效果?

4

5 回答 5

2

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

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

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

  • [完成] 立即返回。

如果您选择实现这一点,请小心。关闭套接字非常简单。然而,“等待完成处理程序”是一种轻描淡写的说法。当服务器的线程和它的析构函数交互时,可能会发生一些微妙的极端情况和竞争条件。

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

于 2009-12-21T19:51:01.397 回答
2

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

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

最后,您可以终止线程 - 但您必须在 boost 之外执行此操作,并了解后果,例如悬空或泄漏资源。如果您正在关闭,这可能不是问题,具体取决于该线程在做什么。

于 2009-12-08T02:28:44.503 回答
1

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

然后线程必须自动关闭。

线程的生成器应在其析构函数中,具有以下内容:

~object()
{
    shutdown_queue.shutdown();   // ask thread to shut down
    thread.join();               // wait until it does
}
于 2010-01-20T06:13:20.070 回答
0
boost::system::error_code _error_code;
client_socket_->shutdown(client_socket_->shutdown_both, _error_code);

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

于 2019-07-17T07:43:05.367 回答
-1

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

于 2013-07-12T09:29:18.957 回答