【发布时间】:2017-06-23 04:01:26
【问题描述】:
我正在尝试解压缩从 boost asio 套接字接收的 zlib 压缩数据。 (版本 1.64.0)
我用boost::asio::streambuf作为接收缓冲区,用boost::iostreams::filtering_istream解压。
如果我一次发送所有压缩数据,我的代码将按预期工作。但是,如果我将压缩数据作为 5 字节分块发送,则代码无法按预期工作。
我创建一个压缩数据如下:
auto str = prepare_compressed_data("Hello world");
数据是:
78 9c f3 48 cd c9 c9 57 28 cf 2f ca 49 01 00 18 ab 04 3d
(Length is 19)
我设置filtering_istream解压如下:
// Prepare decompressing istream
boost::asio::streambuf sbuf;
boost::iostreams::filtering_istream is;
is.push(boost::iostreams::zlib_decompressor());
is.push(sbuf);
这是网络发送-接收仿真代码:
// Network (asio socket send-receive) emulation
auto str_it = str.begin();
auto rest = str.size();
while (rest != 0) {
auto copy_size = std::min(rest, send_size); // send_size is 5
// Emulate receive
// In actual code, it is `socket.read_some(mbuf)`
// and its return value is `copy_size`.
auto mbuf = sbuf.prepare(copy_size);
char* p = boost::asio::buffer_cast<char*>(mbuf);
std::copy(str_it, str_it + copy_size, p);
sbuf.commit(copy_size);
hexdump(std::string(boost::asio::buffer_cast<char const*>(sbuf.data()), sbuf.size()));
std::cout << "sbuf.size():" << sbuf.size() << std::endl;
{ // decompress
std::cout << "<<< try decompress >>>" << std::endl;
while (is) {
std::cout << " `is` has some data." << std::endl;
char buf[buf_size + 1] = { '\0' };
is.read(buf, buf_size);
std::size_t read_size = is.gcount();
std::cout << " read_size:" << read_size << std::endl;
std::cout << " decompressed data: " << buf << std::endl;
// It seems that is.read() consumed 5 bytes data in underlying sbuf
// even if is.gcount() returned 0.
}
std::cout << "<<< decompress loop out >>>" << std::endl;
}
rest -= copy_size;
str_it += copy_size;
}
将str 的一部分(5 个字节分块)复制到sbuf。
内部while循环第一次执行,while (is) {,is.read(buf, buf_size)被执行,下一行is.gcount()返回0,估计是数据不够解压。但是,is 似乎消耗了来自sbuf 的 5 个字节。
然后接下来的5个字节被复制,内部while循环的条件不满足。
因为我错过了什么?
完整的代码在这里: https://gist.github.com/redboltz/1934952be51e73d558fe8cd7e861d4da
我得到了以下输出:
compressed data: 78 9c f3 48 cd c9 c9 57 28 cf 2f ca 49 01 00 18 ab 04 3d
78 9c f3 48 cd
sbuf.size():5
<<< try decompress >>>
`is` has some data.
read_size:0
decompressed data:
<<< decompress loop out >>>
c9 c9 57 28 cf
sbuf.size():5
<<< try decompress >>>
<<< decompress loop out >>>
c9 c9 57 28 cf 2f ca 49 01 00
sbuf.size():10
<<< try decompress >>>
<<< decompress loop out >>>
c9 c9 57 28 cf 2f ca 49 01 00 18 ab 04 3d
sbuf.size():14
<<< try decompress >>>
<<< decompress loop out >>>
如果我一次复制str,我得到了我预期的以下结果。
compressed data: 78 9c f3 48 cd c9 c9 57 28 cf 2f ca 49 01 00 18 ab 04 3d
78 9c f3 48 cd c9 c9 57 28 cf 2f ca 49 01 00 18 ab 04 3d
sbuf.size():19
<<< try decompress >>>
`is` has some data.
read_size:11
decompressed data: Hello world
<<< decompress loop out >>>
【问题讨论】:
标签: c++ boost boost-asio zlib boost-iostreams