質問

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()をいじりましたが、それは完全なストリームを望んでいます。

役に立ちましたか?

解決

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 から代わりに借りた方がいいかもしれません。

他のヒント

ファイルの終わりは、zlibにとって特別なものではありません。コードで見られる問題は、「readAll()」を使用していることです。実際には、ファイルの終わりなどの「エラー」を報告する手段がありません。

" read()"を使用してください。代わりに、ループで。ストリームを読み取り、0バイトの読み取りを返した場合、ストリームの終わりに到達していることを確認できます(もう一方の端が接続を閉じています)。あなたが読んだバッファは、以前のすべての「読み」のバッファに結合します;ループ内で、完全なバッファが提供されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top