Преместване на компресирани низове между C++ и PHP със zlib

Работя по проект, при който уеб сървър на Windows, изпълняващ PHP, комуникира през много бавна връзка със сървър на Linux в задния край, изпълняващ приложение, написано на C++. Тъй като връзката между двете машини е толкова бавна, бих искал да компресирам трафика, движещ се между тях.

Стигнах дотам, че мога да компресирам низ, да го запазя във файл, да прочета файла и да декомпресирам низа в C++ с помощта на Zlib и по същия начин в PHP. Въпреки това, ако се опитам да компресирам низ на един език и да го декомпресирам на другия (както ще се случи в реалния свят), получавам грешки, че компресираните данни са повредени. Също така забелязах, че същият низ, компресиран в C++, води до различен файл, отколкото в PHP, което ме кара да вярвам, че Zlib използва различен алгоритъм за компресиране на всеки език.

Използвам настройките по подразбиране и от двете страни. C++, който използвам за компресиране и декомпресиране, е

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 и го декомпресира само до "hello". Предполагам, че това означава, че правя нещо нередно от страна на 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
Обажданията са в библиотеката. компресиран, компресиранДължина и т.н. са действителните имена на променливите, които използвам, и тъй като 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, който трябва да изхвърли потока към файла. Чета го от страна на C++, като използвам fread(compressed, sizeof(compressed), 1, in); и компресираният е многократно по-голям от размера на файла, така че трябва да се чете в цялото нещо. Във fopen от двете страни използвам b в низа на режима, за да укажа, че това е двоичен файл, но използването му (или липсата му) изглежда не прави разлика. - person Warren Pena; 28.10.2010
comment
Можете да опитате компресиране/декомпресиране от страна на C++ и същото от страна на PHP, за да изключите проблемите с писател/четец от двата края - person Steve Townsend; 29.10.2010
comment
Най-накрая го постигнах. Всъщност всичко се свеждаше до знакови срещу неподписани символи. Оказва се, че трябва да сте много внимателни с това кое е кое и с това как хвърляте от едното към другото, или бързо ще се окажете в бъркотия. - person Warren Pena; 03.11.2010