【问题标题】:Elegantly stop the thread for blocking or non-blocking when accept or receive using asio and C++11使用 asio 和 C++11 在接受或接收时优雅地停止线程以进行阻塞或非阻塞
【发布时间】:2016-02-01 06:09:10
【问题描述】:

我正在将 asio 用于 tcp 服务器,我也计划将 C++11 std 用于线程。我的最终目标是在 Linux 上拥有此应用程序,但我首先使用 Visual Studio 2015 在 Windows 上对其进行测试。

首先我使用阻塞,所以我发现有关于如何停止等待接受的线程的讨论。有 pre-C++11 解决方案,例如 pipe 和 select。我正在寻找asio方式。

    asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));
    backAcceptor = &acceptor;
    tcp::socket socket(io_service);

    asio::error_code ec;
    acceptor.accept(socket, &ec);

第二种方法是使用异步,但我更喜欢只使用 asio 标头。编译抱怨 asio::placeholder 没有这个成员,但根据评论,应用了解决方案:

    asio::async_write(socket_, asio::buffer(message_),
        std::bind(&tcp_connection::handle_write, shared_from_this(),
            std::placeholders::_1,
            std::placeholders::_2
            ));

run() 仍然阻塞在那里。我正在寻找从 main 恢复这个线程的方法。

    asio::io_service io_service;
    tcp_server server(io_service);
    io_service.run();

第三种方式是设置超时here。但这并不能阻止我的接受。另外,答案是在 2012 年。我希望现在有新的解决方案。

更新

为了测试场景,我首先有一个线程在同步accept() 或异步run() 处阻塞。当线程运行时,main 等待 2 秒,并尝试停止线程。然后我等待线程使用 join 完成。

对于第一种方法“Synchronous”,我尝试使用acceptor.cancel() 并且线程到达了join。这是正确的方法吗?

第二种方法“异步”,虽然我还不清楚如何正式停止这个线程,但我成功使用io_service.stop()实际取消了它。

请让我知道我的解决方案是否正确,我会继续尝试不同的解决方案。

【问题讨论】:

  • 只使用 std::placeholders::_2 作为第二个占位符?
  • 编译好了。所以现在我意识到 asio pdf 中的示例仍然使用 run() 阻止。
  • 如果您不想在有外部事件循环的情况下阻塞,您可以使用 run_one 和 poll_one。见stackoverflow.com/questions/8727568/…
  • 需要一个比“在这里投诉”更好的错误指示器。 ::run() 仅在未完成的操作处于提示中时阻塞,除非您创建 io_service::work 对象。您的问题不清楚,因为您要同时提出 3 个问题。无论如何,手动运行 io_service 所花费的时间与使用 ::run() 的时间一样长,并且您将被阻止。阻塞必须发生在某个地方,最终会发生在::run(),这通常是您指定单独的线程或线程池来运行 io_service 的原因。
  • @Ralf,从名字上看,poll_one 看起来像我需要的那个。我会试试的。

标签: c++ linux multithreading c++11 boost-asio


【解决方案1】:

我碰巧用run_one 和没有线程的非典型方法玩过,它特别允许您超时单个“非异步”操作:

事实上,您确实发布了异步操作,但随后您调用 await_operation 并超时:

async_connect(socket, ip::tcp::resolver(ioservice).resolve({address, port}), raise());
await_socket(std::chrono::seconds(6));

这相当于执行同步connect 可能会超时。没有线程、阻塞run() 或其他小狗受到伤害。

查看演示的链接答案


PS。如果您不希望 high_resolution_timerstd::chrono 很好地配合使用,请使用 deadline_timerposix_time

【讨论】:

  • 您对服务器端的建议是什么?您的链接指向一个客户端示例。
  • @splash 我的技术适用于任何可能冗长的操作。因此,您可以在使用异步操作的任何地方应用它,但首选半同步工作流程,就像在这种情况下 OP 一样。
  • 你能提供停止服务器端接受的例子吗?
猜你喜欢
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2011-12-24
  • 2013-06-23
  • 2020-01-16
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
相关资源
最近更新 更多