当使用asio和C++11接受或接收时,优雅地停止线程进行阻塞或非阻塞

Elegantly stop the thread for blocking or non-blocking when accept or receive using asio and C++11

本文关键字:线程 asio C++11      更新时间:2023-10-16

我正在为tcp服务器使用asio,并计划为线程使用C++11 std。我的最终目标是在Linux上拥有这个应用程序,但我首先使用Visual Studio 2015在Windows上测试它。

首先我使用了阻塞,所以我发现有人在讨论如何停止线程等待accept。有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::占位符没有这个成员,但根据评论,应用了解决方案:

    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();

第三种方法是,在这里设置一个超时。但这并没有阻止我接受。另外,答案是在2012年。我希望现在有新的方法来解决这个问题。

更新

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

对于第一个方法"Synchronous",我尝试使用receiver.cancel(),线程到达连接。这是正确的方法吗?

第二个方法"Async",尽管我仍然不清楚如何正式停止这个线程,但我成功地使用io_service.stop()来实际取消它。

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

我碰巧用了一种不典型的run_one方法,没有线程,它特别允许您超时单个"非异步"操作:

  • boost::asio+std::future-关闭套接字后发生访问冲突

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

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

这相当于执行同步connect,但可能会超时。没有螺纹、堵塞run()或其他幼犬受到伤害。

查看演示的链接答案


PS。如果您不想要与std::chrono 配合良好的high_resolution_timer,请将deadline_timerposix_time配合使用