【问题标题】:Interrupt boost::asio synchronous read?中断 boost::asio 同步读取?
【发布时间】:2009-12-06 23:10:47
【问题描述】:

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

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

如何使用 boost 实现类似的效果?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      • [完成] 立即返回。

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

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

      【讨论】:

        【解决方案3】:

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

        然后线程必须自动关闭。

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

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

        【讨论】:

          【解决方案4】:
          boost::system::error_code _error_code;
          client_socket_->shutdown(client_socket_->shutdown_both, _error_code);
          

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

          【讨论】:

            【解决方案5】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-03-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多