Boost logo

Boost Users :

Subject: Re: [Boost-users] std::future::wait_for() not working in Boost UDP socket async receive operation
From: TONGARI J (tongari95_at_[hidden])
Date: 2016-11-28 22:26:59


2016-11-29 5:55 GMT+08:00 <jc.francois_at_[hidden]>:

> 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.



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net