简体   繁体   中英

Boost Async UDP Client

I've read through the boost:asio documentation (which appears silent on async clients), and looked through here, but can't seem to find the forest for the trees here.

I've got a simulation that has a main loop that looks like this:

for(;;)
{
  a = do_stuff1();
  do_stuff2(a);
}

Easy enough.

What I'd like to do, is modify it so that I have:

for(;;)
{
  a = do_stuff1();
  check_for_new_received_udp_data(&b);
  modify_a_with_data_from_b(a,b);
  do_stuff2(a);
}

Where I have the following requirements:

  1. I cannot lose data just because I wasn't actively listening. IE I don't want to lose packets because I was in do_stuff2() instead of check_for_new_received_udp_data() at the time the server sent the packet.
  2. I can't have check_for_new_received_udp_data() block for more than about 2ms, since the main for loop needs to execute at 60Hz.
  3. The server will be running elsewhere, and has a completely erratic schedule. Sometimes there will be no data, othertimes I may get the same packet repeatedly.

I've played with the async UDP, but that requires calling io_service.run(), which blocks indefinitely, so that doesn't really help me.

I thought about timing out a blocking socket read, but it seems you have to cheat and get out of the boost calls to do that, so that's a non-starter.

Is the answer going to involve threading? Either way, could someone kindly point me to an example that is somewhat similar? Surely this has been done before.

To avoid blocking in the io_service::run() you can use io_service::poll_one() .

Regarding loosing UDP packets, I think you are out of luck. UDP does not guarantee delivery, and any part of the network may decide to drop UDP packets if there is much traffic. If you need to ensure delivery you need to have either implement some sort of flow control or just use TCP.

I think your problem is that you're still thinking synchronously. You need to think asynchronously.

  1. Async read on UDP socket - will call handler when data arrives.
  2. Within that handler do your processing on the incoming data. Keep in mind that while you're processing, if you have a single thread, nothing else dispatches. This can be perfectly OK (UDP messages will still be queued in the network stack...).
  3. As a result of this you could be starting other asynchronous operations.

If you need to do work in parallel that is essentially unrelated or offline that will involve threads. Create a thread that calls io_service.run().

If you need to do periodic work in an asynch framework use timers .

In your particular example we can rearrange things like this ( psuedo-code ):

read_handler( ... )
{
   modify_a_with_data_from_b(a,b);
   do_stuff2(a);
   a = do_stuff1();
   udp->async_read( ..., read_handler );
}

periodic_handler(...)
{
  // do periodic stuff
  timer.async_wait( ..., periodic_handler );
}

main()
{
   ...
   a = do_stuff1();
   udp->async_read( ..., read_handler )
   timer.async_wait( ..., periodic_handler );

   io_service.run();
}

Now I'm sure there are other requirements that aren't evident from your question but you'll need to figure out an asynchronous answer to them, this is just an idea. Also ask yourself if you really need an asynchronous framework or just use the synchronous socket APIs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM