Это второе дополнение к моей предыдущей статье «Шифровка потока информации 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
}
}
}