Я работаю с zlib и у меня возникли проблемы с распаковкой. Я пытаюсь распаковать пакеты, которые приходят в мою программу, но правильно распакован только первый пакет. Например :
//first compressed packet
78 5e 72 65 60 08 65 bf cd c0 60 28 98 3f 95 03
08 18 19 19 25 18 4c af b9 32 38 0a a4 d6 6c 6d
6c 60 60 04 42 20 60 31 2b c9 37 61 c9 2c 28 33
e3 cc cd 4c 2e ca 2f ce 4f 2b 61 4e ce cf 65 00
29 38 c0 03 51 c6 7c 9b 81 e5 40 44 32 23 00
//first decompressed packet
//inflate return 0
45 00 00 55 07 db 00 00 31 11 6f 95 08 08 08 08
01 01 01 18 00 35 d6 45 00 41 10 65 7c b5 81 80
00 01 00 01 00 00 00 00 04 36 74 6f 34 04 69 70
76 36 09 6d 69 63 72 6f 73 6f 66 74 03 63 6f 6d
00 00 01 00 01 c0 0c 00 01 00 01 00 00 03 db 00
04 c0 58 63 01
Но когда я пытаюсь распаковать второй пакет, функция «inflate» возвращает мне -3 и ничего не распаковывает. Пример для второго сжатого пакета:
//second compressed packet
//inflate return -3
72 65 60 f0 62 bf 03 36 74 3e c2 d0 77 cb 19 cc
de cc d8 18 8c 30 94 b9 20 b1 92 35 33 bf 38 b1
84 a9 a8 14 c5 24 17 2f 06 96 88 63 e7 ad 01 00
Я пытаюсь инициализировать декомпрессор с параметрами MAX_WBITS, -MAX_WBITS, 30, но это не помогло. Как я могу решить эту проблему?
Пример кода:
//functions
InitZDecompressor = ( int (WINAPI *)( z_stream_s*, int,const char*,int)) GetProcAddress(zlibdll,"inflateInit2_");
ZDecompressor = (int (WINAPI *)(z_stream_s*,int)) GetProcAddress(zlibdll,"inflate");
ResetZDecompressor = (int (WINAPI *)(z_stream_s*)) GetProcAddress(zlibdll,"inflateEnd");
//initialize
__int32 Decoder(unsigned __int8* PDU, unsigned __int32 size, unsigned __int8 * out_b, z_stream_s & stream, bool & IsInit)
{
if (IsDllLoaded == false || PDU == nullptr) { return 0; }//if Zlib DLL was not loaded, or incoming packet is not cTCP
if ( !IsInit )
{
SecureZeroMemory(&stream, sizeof(stream));
auto res = InitZDecompressor( &stream, MAX_WBITS , "1.2.11", sizeof(z_stream_s));//initialize only one time
IsInit = true;
}
stream.next_in = PDU;
stream.avail_in = size;
stream.next_out = out_b;
stream.avail_out = 1048576;
stream.total_out = 0;
__int32 ret = 0;
//inflate
while ( stream.avail_in && ret == 0 )
{
ret = ZDecompressor(&stream, 2);
}
return ret;
}
//inflateEnd
void ResetDecompessor(bool & isInit, z_stream_s & stream)
{
if (isInit){
ResetZDecompressor(&stream);
isInit = false;
memset(&stream, 0 ,sizeof(stream));
}
}
//test func
void testZlib(unsigned __int8 *StPt, __int64 size,z_stream_s & stream,bool & isInit)
{
// StPt - start of compressed data
//size - size of compressed data
//isInit - is zStream already initialize
unsigned __int8 * OutBuf = new unsigned __int8[ 1048576 ];
auto res = zlib->Decoder( StPt,size, OutBuf, stream, isInit );
delete [] OutBuf;
}
Здесь происходит то, что отправитель очищает компрессор дефляции пустым сохраненным блоком, чтобы создать распаковываемый пакет, а затем удаляет последние четыре байта пустого сохраненного блока, ожидая, что вы, получатель, вставите его.
Итак, что вам нужно сделать, это вставить байты 00 00 ff ff
между сжатыми пакетами, а затем распаковать все это как один поток zlib. Не инициализируйте инфляцию для второго пакета — просто продолжайте подавать сжатые данные в инфлятор (включая вставленные байты).
Других решений пока нет …