从boost asio streambuf读取会将字节保持在缓冲区中

Reading from boost asio streambuf keeps bytes in buffer

本文关键字:缓冲区 字节 asio boost streambuf 读取      更新时间:2023-10-16

我在读取boost asio的流时遇到问题。async_read_until的第一次调用给了我460个字节的传输(我用wireshark检查过)。之后,我使用用streambuf指针初始化的istream,将std::copy_n与istreambuf_editor一起使用。这很好,std::copy_n的目标将请求保持到分隔符序列。

奇怪的事情发生在下一次调用async_read_until之后。最后一个字符似乎没有从streambuf中读取,所以下一个处理程序调用给我的比请求的实际大小多一个字节。

将istream与asio的streambuf一起使用有任何限制吗?

除了注释之外,这里还有一个小演示程序,展示了与asio::streambuf交互的两种方式。

一种方法将streambuf封装在i/o流中,另一种方法使用prepare/commit和data/consume的直接访问。

#include <boost/asio.hpp>
#include <iostream>
#include <string>
#include <algorithm>
#include <memory>
namespace asio = boost::asio;
void direct_insert(asio::streambuf& sb, std::string const& data)
{
auto size = data.size();
auto buffer = sb.prepare(size);
std::copy(begin(data), end(data), asio::buffer_cast<char*>(buffer));
sb.commit(size);
}
void stream_insert(asio::streambuf& sb, std::string const& data)
{
std::ostream strm(std::addressof(sb));
strm << data;
}
std::string extract_istream(asio::streambuf& sb)
{
std::istream is(std::addressof(sb));
std::string line;
std::getline(is, line);
return line;
}
std::string extract_direct(asio::streambuf& sb)
{
auto buffer = sb.data();
auto first = asio::buffer_cast<const char*>(buffer);
auto bufsiz = asio::buffer_size(buffer);
auto last = first + bufsiz;
auto nlpos = std::find(first, last, 'n');
auto result = std::string(first, nlpos);
auto to_consume = std::min(std::size_t(std::distance(first, nlpos) + 1), bufsiz);
sb.consume(to_consume);
return result;
}
int main()
{
asio::streambuf buf;
direct_insert(buf, "The cat sat on the matn");
stream_insert(buf, "The cat sat on the matn");
auto s1 = extract_direct(buf);
auto s2 = extract_istream(buf);
std::cout << s1 << "n" << s2 << "n";
}