繁体   English   中英

查找zlib压缩流的结尾

[英]Finding the end of a zlib compressed stream

我正在使用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_completeuncompressed_streamremainder_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
}

此增量解压缩(膨胀)从qbufferqout ,当停止inflate说:“没有更多的”。

也许最好从QuaZip借用。

文件的结尾对于zlib并不特殊。 我在代码中看到的问题是您使用的是“ readAll()”,实际上它没有任何报告“错误”的方式,例如文件结尾。

您应该尝试在循环中使用“ read()”。 如果您读取了流并且返回了0个字节,则可以确保已到达流的末尾(另一端已关闭连接)。 您已读取的缓冲区,将循环中所有先前“读取”的缓冲区合并在一起,将为您提供完整的缓冲区。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM