Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discarding data with boost::asio

I'm using boost::asio in asynchronous mode and I'd like to skip/discard/drop a message that has been sent to me over TCP. I want to do this because I've already read the header for the message and I know that it is of no interest to me. The message may be large so it I would prefer not to allocate space for it and even better not to transfer it into user space at all.

I see boost::asio::null_buffers but it does not appear to be applicable here (see https://svn.boost.org/trac/boost/ticket/3627).

like image 425
mpm Avatar asked Aug 23 '11 20:08

mpm


1 Answers

As far as I know, the BSD socket interface doesn't give you this functionality. You always have to read into a buffer. Now, what you can do in order to not allocate a huge buffer is to read into a smaller buffer in a loop. Something like this:

void skip_impl(tcp::socket& s, int n, boost::function<void(error_code const&)> h
    , char* buf, error_code const& ec, std::size_t bytes_transferred)
{
    assert(bytes_transferred <= n);
    n -= bytes_transferred;
    if (ec || n == 0) {
        delete[] buf;
        h(ec);
        return;
    }

    s.async_read_some(boost::asio::buffer(temp, std::min(4096, n))
        , boost::bind(&skip_impl, boost::ref(s), n, h, temp, _1, _2));
}

void async_skip_bytes(tcp::socket& s, int n, boost::function<void(error_code const&)> h)
{
    char* temp = new char[4096];
    s.async_read_some(boost::asio::buffer(temp, std::min(4096, n))
        , boost::bind(&skip_impl, boost::ref(s), n, h, temp, _1, _2));
}

This has not been passed through a compiler, so there might be silly typos, but it should illustrate the point.

like image 140
Arvid Avatar answered Sep 29 '22 08:09

Arvid