简体   繁体   中英

boost::asio::async_read_until does not read all message

boost::asio::async_read_until does not read all data, and hangs in the middle of the message.

    boost::asio::async_read_until(socket, response, "\n", boost::asio::placeholders::error));
                        [&](const boost::system::error_code &err2, std::size_t lenght)
                        {
                            RUN_CHECK;
                            if (!err2)
                            {
                                RUN_CHECK;
                                std::string r =  this->response_get();
    /*
    .. do stuff here
    */

                            }
                            else
                            {
                                report_error(err2);
                            }
}

Any idea what's wrong? Is not supposed for async_read_until to read until "\\n" is reached?

                  std::string r = this->response_get();

Whatever you do in response_get() you're not correctly using length . This means that any characters received beyond the delimiter ( "\\n" ) are likely also consumed, which means that next read will be lacking the start.

Another issue that might be at play is when your buffer is not dynamic (eg asio::streambuf ) and you didn't reserve enough capacity. Then the async read will complete when the buffer has been filled, even if the delimiter wasn't received.

None of this explains "hang". If you observe a hang, check your server (the sending side) and or networking infrastructure (use a network monitor tool to check that message is actually arriving).

Here's a quick fixup of the code to be self-contained:

#include <boost/asio.hpp>
#include <iostream>

#define RUN_CHECK                                                                                                      \
    do {                                                                                                               \
        std::cout << "Here:" << __LINE__ << "\n";                                                                      \
    } while (0)

struct X {
    boost::asio::io_service io;
    boost::asio::ip::tcp::socket socket{io};

    X() {
        socket.connect({ {}, 6767 });
    }

    boost::asio::streambuf response;

    void foo() {
        boost::asio::async_read_until(socket, response, "\n",
              [&](const boost::system::error_code &ec, std::size_t length) {
                  RUN_CHECK;
                  if (!ec) {
                      RUN_CHECK;
                      std::string r = this->response_get(length);
                      /*
                      .. do stuff here
                      */

                  } else {
                      report_error(ec);
                  }
              });
    }

    std::string response_get(std::size_t length) {
        std::string result;
        std::copy_n(boost::asio::buffers_begin(response.data()), length, back_inserter(result));
        return result;
    }

    void report_error(boost::system::error_code ec) {
        std::cout << "Error: " << ec.message() << "\n";
    }
};

int main() {
    X x;
    x.foo();

    x.io.run();
}

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