Перемещение сжатых строк между C++ и PHP с помощью zlib

Я работаю над проектом, в котором веб-сервер Windows, работающий под управлением PHP, взаимодействует через очень медленное соединение с внутренним сервером Linux, на котором запущено приложение, написанное на C++. Поскольку соединение между двумя машинами очень медленное, я хотел бы сжать трафик, проходящий между ними.

Я добрался до того места, где я могу сжать строку, сохранить ее в файл, прочитать файл и распаковать строку в C++ с помощью Zlib, а также в PHP. Однако, если я попытаюсь сжать строку на одном языке и распаковать ее на другом (как это происходит в реальном мире), я получаю ошибки, свидетельствующие о том, что сжатые данные повреждены. Я также заметил, что одна и та же строка, сжатая в C++, приводит к другому файлу, чем в PHP, что наводит меня на мысль, что Zlib использует разные алгоритмы сжатия для каждого языка.

Я использую настройки по умолчанию для обеих сторон. С++, который я использую для сжатия и распаковки,

compress((Bytef*)compressed, (uLongf*)&compressedLength, (Bytef*)uncompressed, (uLong)uncomressedLength);
uncompress((Bytef*)uncompressed, (uLongf*)&uncomressedLength, (Bytef*)compressed, (uLong)compressedLength);

в то время как PHP-код

$compressed = gzcompress($uncompressed);
$uncompressed = gzuncompress($compressed);

Почему это приводит к разным сжатым строкам? Из-за этого проблемы с декомпрессией? Что я должен сделать, чтобы заставить это работать? Кроме того, я не привержен Zlib. Zlib — это то, что было обнаружено моим первоначальным исследованием, но если есть лучший способ сделать это, я весь в ушах.

Редактировать: На самом деле, после небольшого дополнительного тестирования выяснилось, что C++ работал с моим первоначальным тестовым примером, но не всегда. Я попробовал это с вводом «hellohellohello», и при распаковке он сообщил о Z_DATA_ERROR и распаковал его до просто «привет». Я предполагаю, что это означает, что я делаю что-то неправильно на стороне C++, что может объяснить, почему PHP недоволен распаковкой сжатых строк C++.

Редактировать 2: я попробовал пример программы zpipe.c, и он правильно распаковывает строки, сжатые PHP, и создает сжатые строки, которые PHP может распаковать. Очевидно, проблема(ы) существуют в моем коде C++. Либо я неправильно использую сжатие и распаковку, либо я неправильно читаю и записываю файл. Ни программы сжатия, ни программы распаковки корректно не взаимодействуют с zpipe.

Обновление: теперь я могу сжать строку с помощью PHP и прочитать ее с помощью PHP или C++, и я могу сжать строку с помощью C++ и прочитать ее с помощью C++, но пытаюсь прочитать это с PHP приводит к предупреждению PHP: gzuncompress(): ошибка данных. Что может быть другим, что может вызвать эту комбинацию рабочих/нерабочих сценариев?


person Warren Pena    schedule 28.10.2010    source источник
comment
Это не тот C++, который вы используете для (де)сжатия, это просто объявления функций.   -  person Ignacio Vazquez-Abrams    schedule 28.10.2010
comment
Это звонки в библиотеку. сжатый, сжатыйLength и т. д. являются фактическими именами переменных, которые я использую, и, поскольку Zlib использует свои собственные типы, а не стандартные типы, я привожу их, когда делаю вызов.   -  person Warren Pena    schedule 28.10.2010
comment
Не могли бы вы опубликовать свой полностью обновленный код, пожалуйста? Спасибо.   -  person cedivad    schedule 27.12.2011


Ответы (1)


Уровень сжатия Zlib по умолчанию равен 6. Вы можете попробовать передать его в качестве второго параметра в gzcompress для PHP.

string gzcompress ( string $data [, int $level = -1 ] )

Из руководства ZLIB:

Уровень сжатия должен быть Z_DEFAULT_COMPRESSION или находиться в диапазоне от 0 до 9: 1 дает наилучшую скорость, 9 — наилучшее сжатие, 0 — полное отсутствие сжатия (входные данные просто копируются поблочно). Z_DEFAULT_COMPRESSION запрашивает компромисс по умолчанию между скоростью и сжатием (в настоящее время эквивалентно уровню 6)

person Steve Townsend    schedule 28.10.2010
comment
Вы также можете убедиться, что другие настройки и, возможно, версии библиотек одинаковы или совместимы. - person ssube; 28.10.2010
comment
Изменение уровня сжатия, похоже, не влияет на сторону PHP. Он работает независимо от установленного уровня. Неправильная декомпрессия со стороны C++ отличается, если я варьирую уровень сжатия, но по крайней мере для 0, 6 и 9 она всегда неверна. - person Warren Pena; 28.10.2010
comment
Странный. Мне нужно было заставить ZLIB работать с C++, C# и Java, и хотя файлы были разными, распаковка всегда работала. Есть ли какая-то операция очистки потока или файла, которую вы не выполняете на обоих концах? - person Steve Townsend; 28.10.2010
comment
Когда я сжимаю с помощью PHP, последняя строка скрипта — это fclose, которая должна сбрасывать поток в файл. Я читаю его на стороне С++, используя fread(compressed, sizeof(compressed), 1, in); и сжатый во много раз больше, чем размер файла, поэтому он должен читаться целиком. В fopen с обеих сторон я использую b в строке режима, чтобы указать, что это двоичный файл, но его использование (или его отсутствие), похоже, не имеет значения. - person Warren Pena; 28.10.2010
comment
Вы можете попробовать сжать/распаковать на стороне С++ и то же самое на стороне PHP, чтобы исключить проблемы с записью/чтением на обоих концах. - person Steve Townsend; 29.10.2010
comment
Наконец-то я заработал. На самом деле все сводилось к знаковым и неподписанным символам. Оказывается, вы должны быть очень осторожны с тем, что есть что, и с тем, как вы переводите от одного к другому, иначе вы быстро закончите беспорядок. - person Warren Pena; 03.11.2010