查找 zlib 压缩流的末尾
我正在使用 Qt 开发 NMDC 客户端(p2p、DC++ 等)。协议本身非常简单:
$command parameters|
除了压缩:
“ZPipe 的工作原理是向客户端发送命令 $ZOn|。在 $ZOn 之后,将跟随一个包含命令的 ZLib 压缩流。该流将以 ZLib 定义的 EOF 结尾。(压缩流中没有 $ZOff !)”
相关代码如下:
QTcpSocket *conn;
bool compressed;
QByteArray zbuffer;
QByteArray buffer;
// ...
void NMDCConnection::on_conn_readyRead() {
// this gets called whenever we get new data from the hub
if(compressed) { // gets set when we receive $ZOn
zbuffer.append(conn->readAll());
// Magic happens here
if( stream_is_complete ) {
buffer.append(uncompressed_stream);
buffer.append(remainder_of_data);
compressed = false;
}
} else {
buffer.append(conn->readAll());
};
parse(buffer);
}
那么,如何获取 stream_is_complete
、uncompressed_stream
和 remainder_of_data
的值?我无法查找下一个“$”,因为流可以包含它。我尝试在 zlib 文档中寻找类似 EOF 的东西,但没有这样的东西,事实上,每个流都以看似随机的字符结尾。
我也尝试过 qUncompress(),但这需要一个完整的流,仅此而已。
I'm working on an NMDC client (p2p, DC++ and friends) with Qt. The protocol itself is pretty straightforward:
$command parameters|
Except for compression:
"ZPipe works by sending a command $ZOn| to the client. After $ZOn a ZLib compressed stream containing commands will follow. This stream will end with an EOF that ZLib defines. (there is no $ZOff in the compressed stream!)"
Here's the relevant code:
QTcpSocket *conn;
bool compressed;
QByteArray zbuffer;
QByteArray buffer;
// ...
void NMDCConnection::on_conn_readyRead() {
// this gets called whenever we get new data from the hub
if(compressed) { // gets set when we receive $ZOn
zbuffer.append(conn->readAll());
// Magic happens here
if( stream_is_complete ) {
buffer.append(uncompressed_stream);
buffer.append(remainder_of_data);
compressed = false;
}
} else {
buffer.append(conn->readAll());
};
parse(buffer);
}
So, how do I get the values for stream_is_complete
, uncompressed_stream
, and remainder_of_data
? I can't look for the next '$' because the stream can contain it. I tried looking for something resembling an EOF in the zlib documentation, but there is no such thing, in fact, every stream ends with a seemingly random character.
I also played around with qUncompress(), but that wants a complete stream, nothing less, nothing more.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你直接用zlib吗?
完全未经测试...
这会从
qbuffer
增量解压(膨胀)到qout
,并在inflate
说“不再”时停止。也许借用 QuaZip 会更好。
Are you using zlib directly?
Totally untested...
This incrementally decompresses (inflates) from
qbuffer
toqout
, and stops wheninflate
says "no more".Maybe it would be better to borrow from QuaZip instead.
文件结尾对于 zlib 来说并不特殊。我在您的代码中看到的问题是您使用“readAll()”,它实际上没有任何报告“错误”的方法,例如文件结尾。
您应该尝试在循环中使用“read()”。如果您读取流并且它返回读取的 0 个字节,则可以确定您已到达流的末尾(另一端已关闭连接)。您读取的缓冲区,加上循环中所有先前“读取”的缓冲区,将为您提供完整的缓冲区。
The end of file is not special for zlib. The problem I see with your code is that you use "readAll()", which actually does not have any means of reporting "errors", such as end of file.
You should try to use "read()" instead, in a loop. If you read the stream and it returns 0 bytes read, you can be sure you've reached the end of stream (the other end has closed the connection). The buffer you've read, joining those of all the previous "reads" in the loop, will give you the complete buffer.