سؤال

وأنا أعمل على عميل شركة الجرافات البحرية الوطنية (P2P، DC ++ والأصدقاء) مع كيو تي. بروتوكول نفسها واضحة جدا:

$command parameters|

ضغط :

<اقتباس فقرة>   

و"ZPipe يعمل عن طريق إرسال أمر $ زون |. إلى العميل بعد $ زون لZLIB ضغط تيار تحتوي على الأوامر واتباع هذا التيار سوف ينتهي مع EOF التي تعرف ZLIB (لا يوجد $ زوف في تيار مضغوط. !) "

وهنا رمز ذات الصلة:

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؟ أنا لا يمكن أن ننظر ل '$' القادم لأن تيار يمكن أن تحتوي عليه. حاولت تبحث عن شيء تشبه EOF في وثائق زليب، ولكن لا يوجد شيء من هذا القبيل، في الواقع، كل تيار ينتهي بحرف تبدو عشوائية.

وكما لعبت حوالي مع qUncompress ()، ولكن الذي يريد تيار كامل، لا شيء أقل من ذلك، لا شيء أكثر من ذلك.

هل كانت مفيدة؟

المحلول

هل تستخدم زليب مباشرة؟

ولم تختبر تماما ...

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 بدلا من ذلك.

نصائح أخرى

ونهاية الملف ليست خاصة لزليب. المشكلة أرى مع الشفرة هي التي تستخدمها "readAll ()"، والتي في الواقع لا يملك أي وسيلة لإبلاغ "أخطاء"، مثل نهاية الملف.

ويجب عليك محاولة استخدام "قراءة ()" بدلا من ذلك، في حلقة. إذا كنت تقرأ تيار وتقوم بإرجاع 0 بايت قراءة، يمكنك أن تكون متأكدا من أنك قد وصلت إلى نهاية تيار (الطرف الآخر قد أغلق الاتصال). المخزن المؤقت كنت قد قرأت، والانضمام إلى تلك عن السابق "يقرأ" في الحلقة، سوف تعطيك عازلة كاملة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top