C ++ Boost :: ASIO:第二次调用io_context :: run后出现系统错误995

时间:2018-05-23 08:51:51

标签: c++ boost asio

使用asio 1.66.0 Windows实现

时遇到以下情况我遇到了麻烦
  1. bind socket
  2. 运行io_context
  3. 停止io_context
  4. 关闭套接字
  5. 重启io_context
  6. 重复1-4
  7. 在第二次迭代中调用io_context :: run后跟系统错误995

      

    I / O操作因线程退出或中断而中止   申请要求

    看起来这个错误来自套接字闭包:asio使用PostQueuedCompletionStatus / GetQueuedCompletionStatus来表示自己调用了io_context :: stop。但是由socket_.async_receive_from中的WSARecvFrom排队的I / O操作失败,因为socket已关闭,并且在下一次调用io_context :: run时,它是我在处理程序中传递给socket_.async_receive_from的第一个。

    asio io_context的意图是什么?如何在连续迭代中避免此错误?

    如果我通过关闭套接字来停止io_context :: run,那么所有工作都会有相同的错误并且看起来很脏。 另一个奇怪的事情是,如果我在收到错误后继续使用do_receive,我将收到与先前迭代次数一样多的错误,然后我将从套接字接收数据。

    // based on boost_asio/example/cpp11/multicast/receiver.cpp
    // https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/example/cpp11/multicast/receiver.cpp
    
    #include <array>
    #include <iostream>
    #include <string>
    #include <boost/asio.hpp>
    #include <future>
    #include <chrono>
    #include <thread>
    
    using namespace std::chrono_literals;
    
    constexpr short multicast_port = 30001;
    
    class receiver
    {
    public:
        explicit receiver(boost::asio::io_context& io_context) : socket_(io_context)
        {}
    
        ~receiver()
        {
            close();
        }
    
        void open(
            const boost::asio::ip::address& listen_address,
            const boost::asio::ip::address& multicast_address)
        {
            // Create the socket so that multiple may be bound to the same address.
            boost::asio::ip::udp::endpoint listen_endpoint(
                listen_address, multicast_port);
            socket_.open(listen_endpoint.protocol());
            socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
            socket_.bind(listen_endpoint);
    
            // Join the multicast group.
            socket_.set_option(
                boost::asio::ip::multicast::join_group(multicast_address));
    
            do_receive();
        }
    
        void close()
        {
            if (socket_.is_open())
            {
                socket_.close();
            }
        }
    
    private:
        void do_receive()
        {
            socket_.async_receive_from(
                boost::asio::buffer(data_), sender_endpoint_,
                [this](boost::system::error_code ec, std::size_t length)
                {
                    if (!ec)
                    {
                        std::cout.write(data_.data(), length);
                        std::cout << std::endl;
    
                        do_receive();
                    }
                    else
                    {
                        // A call to io_context::run in second iteration is followed by system error 995
                        std::cout << ec.message() << std::endl;
                    }
                });
        }
    
        boost::asio::ip::udp::socket socket_;
        boost::asio::ip::udp::endpoint sender_endpoint_;
        std::array<char, 1024> data_;
    };
    
    int main(int argc, char* argv[])
    {
        try
        {
            const std::string listen_address = "0.0.0.0";
            const std::string multicast_address = "239.255.0.1";
    
            boost::asio::io_context io_context;
            receiver r(io_context);
            std::future<void> fut;
    
            for (int i = 5; i > 0; --i)
            {
                io_context.restart();
                r.open(
                    boost::asio::ip::make_address(listen_address),
                    boost::asio::ip::make_address(multicast_address));
                fut = std::async(std::launch::async, [&](){ io_context.run(); });
                std::this_thread::sleep_for(3s);
                io_context.stop();
                fut.get();
                r.close();
            }
    
        }
        catch (std::exception& e)
        {
            std::cerr << "Exception: " << e.what() << "\n";
        }
    
        return 0;
    }
    

0 个答案:

没有答案