boost::asio::async_read_until reads all data instead of just some

雨燕双飞 提交于 2019-12-01 15:11:25

Read the description of async_read_until carefully. It says:

After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter.

What this means in your case is that inside handle_read(), you should only access the first bytes_transferred bytes from the buffer. As of now, your bytes_transferred parameter is unused.

The answer by Cubbi is correct: async_read_until() might read extra data into the buffer.

The other answer by ecoretchi is slightly dangerous. It is not incorrect, but only works work this specific question, which reads input word by word (until ' ').

If you are reading input line by line (until '\n'), you will lose data with that solution. This happens because if you use commit(), and >> operator splits your data at something else than newline (for example, you have numbers and whitespaces in the data) all subsequent data is lost.

When you are reading line by line, you should to use getline() to get one line from the buffer. This leaves rest of the data waiting in the streambuf class and allows you to read it with subsequent calls. This is also the reason you must have the streambuf as a member variable, not as a local variable in a function; if it was a local variable, any extra data beyond the first line would be lost.

std::istream is(&buffer);
std::string result_line;
std::getline(is, result_line);

This is by design. Asio does not have good place to store excess data, so it handles them to you. Asio is not parser library, take a look at boost::spirit, or do parsing ad hoc, like our ancestors. :)

Try this:

void handle_read(const boost::system::error_code& error,
      size_t bytes_transferred)
  {

    buffer.commit(bytes_transferred);
    std::istream istrm(&buffer);
    std::string str; 
    istrm>>str;
    ...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!