我正在使用 Qt 开发 NMDC 客户端(p2p、DC++ 和 friend )。协议(protocol)本身非常简单:
$command parameters|
除了 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!)"
相关代码如下:
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(),但它需要一个完整的流,仅此而已。
最佳答案
你是直接使用 zlib 吗?
完全未经测试...
z_stream zstrm;
QByteArray zout;
// when you see a $ZOn|, initialize the z_stream struct
parse() {
...
if (I see a $ZOn|) {
zstrm.next_in = Z_NULL;
zstrm.avail_in = 0;
zstrm.zalloc = Z_NULL;
zstrm.zfree = Z_NULL;
zstrm.opaque = 0;
inflateInit(&zstrm);
compressed = true;
}
}
void NMDCConnection::on_conn_readyRead() {
if (compressed) {
zbuffer.append(conn->readAll());
int rc;
do {
zstrm.next_in = zbuffer.data();
zstrm.avail_in = zbuffer.size();
zout.resize(zstrm.total_out + BLOCK_SIZE);
zstrm.next_out = zout.data() + zstrm.total_out;
zstrm.avail_out = BLOCK_SIZE;
rc = inflate(&zstrm, Z_SYNC_FLUSH);
zbuffer.remove(0, zstrm.next_in - zbuffer.data());
} while (rc == Z_OK && zstrm->avail_out == 0);
if (rc == Z_STREAM_END) {
zout.truncate(zstrm.total_out);
buffer.append(zout);
zout.clear();
buffer.append(zbuffer);
zbuffer.clear();
compress = false;
inflateEnd(&zstrm);
}
else if (rc != Z_OK) {
// ERROR! look at zstrm.msg
}
}
else // whatever
}
这会逐渐从 qbuffer
解压缩(膨胀)到 qout
,并在 inflate
说“不再”时停止。
或许向QuaZip借用会更好相反。
关于c++ - 查找 zlib 压缩流的结尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1637938/