Это второе дополнение к моей предыдущей статье «Шифровка потока информации PHP-HTTP-Qt». Для того что бы разобраться с тем что здесь написано, следует сначала ознакомиться с ней.
Вопрос о возможности их сжатия потока естественно возникает в связи с постоянной передачей больших объёмов разряженных данных (в формате XML) множеству клиентов. Тем более что у конечных пользователей программ-клиантов может быть и не быстрый доступ в Интернет, и сжатие в этом случае может дать существенный выйгрыш в скорости работы.
Я делаю сжатие/разжатие сразу в паре с шифровкой/дешифровкой и так же в связи с шифровкой о нём сейчас рассказываю, тем более что это делается и на стороне сервера и на стороне клиента подобным образом. Но вы, естественно, можете попробовать сделать сжатие/разжатие и без шифровки.
Для сдатия в PHP я использовал всё поточный фильтр zlib.deflate. На стороне клиента я применил класс QtIOCompressor из подзаброшенной ныне коллекции-библиотеки Qt Solutions.
Что бы XML лучше ужался, конечно, надо сжать его до шифровки, а не после.
В моём коде сжатие происходит опционально, в зависимости от значения переменной $compress в PHP и .. в коде клиента C++.
Итак, установка сжимающего фильтра на PHP (естественно, соответствующий фильтр должен быть доступен; проверка: phpinfo() ) выглядит так:if ($compress=="RawZip")
{
$compress_alg = "zlib.deflate";
}
else
{
$compress_alg = false;
}
if ($compress_alg)
{
stream_filter_append($f, $compress_alg, STREAM_FILTER_WRITE);
}
В исходнике в статье про шифрование место, где фильт вставляется у меня помечено комментарием: ...[*]....
В программе клиенте поток-декомпрессор вставляется так:
if (use_compression()) // if use decompressor { // the input stream is compressed m_decompressor = new QtIOCompressor(m_decrypter); // QtIOCompressor *m_decompressor; m_decompressor->setStreamFormat(QtIOCompressor::RawZipFormat); m_decompressor->open(QIODevice::ReadOnly); m_xmlsource = new QXmlInputSource(m_decompressor); } else { // the input stream isn't compressed m_xmlsource = new QXmlInputSource(m_decrypter); }(Соответствующее место в исходнике я помечетил комменарием // [**]).
void WorkplaceTab::onReadyRead() { if ( m_reader==NULL || m_xmlsource==NULL ) { qDebug() << "WorkplaceTab::onReadyRead() - warning"; return; } if (m_first) { // выполняется один раз - при приёме превой порции данных qDebug() << "m_reader->parse(m_xmlsource, true);"; if (!m_reader->parse(m_xmlsource, true)) to_idle_state(); // прекращение режима приёма m_first = false; } long watchdog = 100; while ( m_decrypter!=NULL && (m_decompressor!=NULL? m_decompressor->bytesAvailable(): m_decrypter->bytesAvailable())>0 ) { m_xmlsource->fetchData(); if (!m_reader->parseContinue()) to_idle_state(); // прекращение режима приёма if (watchdog--<0) break; } } void WorkplaceTab::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { logmessage( tr("%1 bytes and %2 rows loaded").arg(bytesReceived).arg(m_row) ); if (bytesReceived==bytesTotal) { // выполняется один раз - после приёма последней порции данных qDebug() << "WorkplaceTab::onDownloadProgress LAST TIME"; if (m_reader==NULL || m_xmlsource==NULL || m_reply==NULL) { qDebug() << "Warning: m_reader==NULL or m_xmlsource==NULL or m_reply==NULL!"; return; } long watchdog=1000000; bool b=true; while ( b && m_xmlsource->data().length()>0 && --watchdog ) { b = m_reader->parseContinue(); } if (b) { m_xmlsource->next(); // и ещё раз - вхолостую - m_reader->parseContinue(); // что бы вызвалось QXmlInputSource::EndOfDocument } } }
← Previous day | (Calendar) | Next day → |