Sign in to follow this  
toglia

Boost Asio receiving old packets, quick questions!

Recommended Posts

I have been messing around Boost Asio for some days now but I got stuck with this weird behavior. Please let me explain. Computer A is sending continuos udp packets every 500 ms to computer B, computer B desires to read A's packets with it own velocity but only wants A's last packet, obviously the most updated one. It has come to my attention that when I do a: mSocket.receive_from(boost::asio::buffer(mBuffer), mEndPoint); I can get OLD packets that were not processed (almost everytime). Does this make any sense? A friend of mine told me that sockets maintain a buffer of packets and therefore If I read with a lower frequency than the sender this could happen. ¡? So, the first question is how is it possible to receive the last packet and discard the ones I missed? Later I tried using the async example of the Boost documentation but found it did not do what I wanted. http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/tutorial/tutdaytime6.html From what I could tell the async_receive_from should call the method "handle_receive" when a packet arrives, and that works for the first packet after the io_service was "run". If I wanted to keep listening the port I should call the async_receive_from again in the handle code. right? BUT what I found is that by doing that I start an infinite loop, it doesn't wait till the next packet, it just enters "handle_receive" again and again and again. So my second question is, do I have to use threads to use the async receive method properly, I must be missing something, sounded like the async approach should have been easier to implement. Thanks for you attention.

Share this post


Link to post
Share on other sites
Quote:
BUT what I found is that by doing that I start an infinite loop, it doesn't wait till the next packet, it just enters "handle_receive" again and again and again.


Any errors?

Can you post the handler and resubmit code?

Quote:
If I read with a lower frequency than the sender this could happen. ¡?
Yes. Or, the socket could receive a misplaced packet from somewhere else. Or a duplicate packet.

If doing synchronous read, read until there are no more packets outstanding - not on one-for-one basis. Admittedly, last I checked, asio made it somewhat annoying to work with non-blocking sockets, so it's either blocking or async reads.

Share this post


Link to post
Share on other sites
Quote:

If doing synchronous read, read until there are no more packets outstanding


You mean like:


while(mSocket.receive_from(boost::asio::buffer(mBuffer), mEndPoint)){}


I can't try it cause I'm at home...



The Async doesn't give error, and its something like:


class UDPServer {

private:
udp::socket mSocket;
udp::endpoint mEndPoint;
boost::array<char, 80> mBuffer;

public:
UDPServer(boost::asio::io_service& io_service) :
mEndPoint(udp::v4(), XXXX),
mSocket(io_service, mEndPoint) {
start_receive();
}

private:

void start_receive() {
mSocket.async_receive_from(
boost::asio::buffer(mBuffer), mEndPoint,
boost::bind(
&UDPServer::handle_receive,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}

void handle_receive(const boost::system::error_code& error,std::size_t) {
if (!error || error == boost::asio::error::message_size) {
// Do something with buffer
start_receive();
}
}

};

int main() {
boost::asio::io_service io_service;
UDPServer server(io_service);
io_service.run();
return 0;
}


That code is very similar to the boost tutorial, but it never stops entering the handle_receive method (infinitely) even though I know the udp packets come with some time spacing between them.

[Edited by - toglia on May 4, 2010 11:18:52 PM]

Share this post


Link to post
Share on other sites
Is the packet you send larger than 80 bytes? Note the error conditions. It would help to print the values you get inside the receive handler.

Also, the kernel will have a buffer of received packets. When/if that buffer gets full, the kernel will generally drop newer packets that receive, until you read some packets to make space. If you want to reduce the amount of buffering, then there are ioctl()s you can call to suggest a smaller buffer to the socket implementation.

Share this post


Link to post
Share on other sites
Quote:
Is the packet you send larger than 80 bytes?

The packet is a bit smaller, say 75.

Quote:
Note the error conditions. It would help to print the values you get inside the receive handler.

It enters the condition meaning it doesn't get any errors. If I would print the mBuffer inside the "handle_receive" I would surely get the updated data from the socket. The problem is I get into an infinite loop (stopping completely the program).

To solve the synchronous implementation I have been suggested to use a smaller receive buffer size with:
http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio/reference/basic_datagram_socket/receive_buffer_size.html
Then I would clean the buffer on each recieve.

But the async solution is still unsolved. Does anyone know how to properly implement the async receive? How can I make the program enter the handler only when a packet arrives?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this