Frage

Ich arbeite an einem NMDC-Client (p2p, DC ++ und Freunde) mit Qt. Das Protokoll selbst ist ziemlich einfach:

$command parameters|

Mit Ausnahme von Kompression :

  

"ZPipe funktioniert, indem Sie einen Befehl $ ZON Senden |. An den Client Nach $ ZON ein ZLib komprimierten Strom Befehlen folgen Dieser Strom wird mit einem EOF-Ende, die ZLib definiert (es gibt keine $ Zoff im komprimierten Strom.. !) "

Hier ist der relevante 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, wie bekomme ich die Werte für stream_is_complete, uncompressed_stream und remainder_of_data? Ich kann nicht für den nächsten ‚$‘ aussehen, weil der Strom es enthalten kann. Ich habe versuchte die Suche nach etwas ein EOF in zlib Dokumentation ähnlich, aber es gibt nicht so etwas in der Tat, jeder Strom endet mit einem scheinbar zufälligen Charakter.

Ich spielte auch mit qUncompress (), aber das will einen kompletten Strom, nichts weniger, nicht mehr.

War es hilfreich?

Lösung

Sind Sie zlib direkt mit?

Völlig ungetestet ...

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
}

Dieses dekomprimiert inkrementell (aufbläst) von qbuffer zu qout, und stoppt, wenn inflate sagt "nicht mehr".

Vielleicht wäre es besser, von leihen QuaZip statt.

Andere Tipps

Das Ende der Datei ist für zlib nicht besonders. Das Problem, das ich mit Ihrem Code zu sehen ist, dass Sie „ReadAll ()“ verwenden, das hat eigentlich keine Mittel der Berichterstattung „Fehler“, wie das Ende der Datei.

Sie sollten versuchen, "read ()" statt, in einer Schleife zu verwenden. Wenn Sie den Stream zu lesen und es gibt 0 Byte zu lesen, können Sie sicher sein, das Ende des Stroms erreicht haben (das andere Ende der Verbindung geschlossen hat). Der Puffer Sie gelesen haben, die bisherige „liest“ in der Schleife die aller anschließen, geben Sie den vollständigen Puffer.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top