2016-11-29 5:55 GMT+08:00 <jc.francois@gmail.com>:
The good people over at stackoverflow were not able to help me with this issue that I expected to be trivial.

I am writing a UDP server app with Boost that should listen on a socket for 5 seconds and if no datagram has been received within these 5 seconds, move on to do other things.

After some research I decided to try the solution based on std::future.

The problem is that the call to wait_for() always times out as if no data was received. But if I set a breakpoint on the line that executes after the timeout and that I inspect variables I see that the buffer contains the received datagram and the remote_endpoint object contains the address of the client. In other words the socket receive works as expected but the std::future::wait_for() does not react. why?

Here is my test server code:

{
    try
    {
        boost::asio::io_service io_service;
        boost::asio::io_service::work work(io_service);
        std::thread thread([&io_service]() { io_service.run(); });

        udp::socket socket(io_service, udp::endpoint(udp::v4(), 10000));
        char recv_buf[8];

        for (;;)
        {
            ZeroMemory(recv_buf, 8);
            udp::endpoint remote_endpoint;
            std::future<std::size_t> recv_length;

            recv_length = socket.async_receive_from(
                boost::asio::buffer(recv_buf),
                remote_endpoint,
                0,
                boost::asio::use_future);

            if (recv_length.wait_for(
                std::chrono::seconds(5)) == std::future_status::timeout)
            {
                printf("time out. Nothing received.\n");
            }
            else
            {
                printf("received something: %s\n", recv_buf);
            }
        }
        io_service.stop();
        thread.join();
    }
    catch (std::exception& e)
    {
        printf("Error: %s\n", e.what());
    }

    return 0;
}

The problem only happens if you have previous timeout. 
You can call socket.cancel() in the timeout branch.

I think the problem is that, if you don't call socket.cancel() on timeout, in the next round you're calling async_receive_from before the previous call completes, which is not allowed.