2016-11-29 5:55 GMT+08:00
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::futurestd::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.