Zlib uncompress возвращает Z_DATA_ERROR

Я работаю над клиент-серверным приложением, где клиент сжимает данные размером 2 МБ, отправляет их на сервер, сервер получает данные, распаковывает их и записывает в файл.

Для некоторых пакетов распаковка не удалась, и я добавил сумму MD5 как к коду на стороне клиента, так и к коду на стороне сервера, а также провел отладку с использованием распаковки на стороне клиента после сжатия данных. Те же параметры, которые проходят для функции распаковки на стороне клиента, не работают с Z_DATA_ERROR на стороне сервера. Сумма данных MD5 кажется такой же. Я совершенно не знаю, что я мог бы сделать дальше.

Код на стороне сервера выглядит так:

int ret = uncompress((Bytef*)unCompressedBuffer, &dwUncompressedBytes, (const Bytef*) receivedBuffer+525, dwBlockLength);

    if (ret == Z_OK)
    {

    }
    else
    {

        std::cout << " Uncompression failed for Block: " << iBlock << std::endl;

        std::cout << " PacketType: 4" << " Block Number:" << iBlock << " Length:" << dwBlockLength << "Error:" << ret << std::endl;

        PrintMD5SumResult((PBYTE)receivedBuffer+525, compressedSize-525);
        std::cout << " Uncompressed MD5 Checksum:0";
        PrintMD5SumResult((PBYTE)unCompressedBuffer, dwUncompressedBytes);

        }
}

Код клиента выглядит так:

int ret = compress2(l_pCompressData + 4, &destLen, 
        (const Bytef*) pBlockData, dwBlockSize, 6); 

memcpy(m_pWriteBuffer+525, l_pCompressData, destLen);
    m_dwWriteBytes = destLen+525;

std::cout << " \n Compressed MD5 Sum:0";
PrintMD5SumResult(m_pWriteBuffer, m_dwWriteBytes);
PrintMD5SumResult(m_pWriteBuffer+525, m_dwWriteBytes-525);

int ret = uncompress(m_pUnCompressData, &uncomLen, (const Bytef*)m_pWriteBuffer+525, destLen);

if(ret != Z_OK)
{
    std::cout << " Uncompression has failed." << std::endl;
}
else
{
    //std::cout << " UnCompressed MD5 Sum:0";
    //PrintMD5SumResult((PBYTE)m_pUnCompressData, md5Output, dwBlockSize);
}

// Write the 2MB to the network
WriteDataOverNetwork(m_NetworkStream, m_pWriteBuffer, m_dwWriteBytes, &dwNumBytes, TRUE);

Я сузил проблему до следующего фрагмента кода в zlib, но мне трудно его понять. В функции inflate() (ZSWAP32(hold)) != state->check) этот оператор не работает. Может ли кто-нибудь помочь мне здесь? Здесь используется MD5sum из библиотеки Boton C++.

    case CHECK:
            if (state->wrap) {
                NEEDBITS(32);
                out -= left;
                strm->total_out += out;
                state->total += out;
                if (out)
                    strm->adler = state->check =
                        UPDATE(state->check, put - out, out);
                out = left;
                if ((
#ifdef GUNZIP
                     state->flags ? hold :
#endif
                     ZSWAP32(hold)) != state->check) {
                    strm->msg = (char *)"incorrect data check";
                    state->mode = BAD;
                    break;
                }

person Sivaram Kannan    schedule 06.06.2012    source источник
comment
MD5 кажется таким же? Являются ли MD5 сжатых данных на двух сторонах одинаковыми или нет? В клиентском коде вы выполняете MD5 для m_dwWriteBytes-525 байт, но распаковываете байты destLen. Непонятно, как m_dwWriteBytes обновляется с помощью результата destLen, полученного с помощью compress().   -  person Mark Adler    schedule 06.06.2012
comment
Извините за путаницу. Buffer+525 фактически является началом сжатых данных. MD5 (буфер) был просто для того, чтобы убедиться, что все данные получены правильно. Что касается uncompress destLen на стороне клиента, то это результат работы функции compress2 ранее. На стороне сервера я получаю его в пакете по смещению и читаю в dwBlockLength. Я ввел код, все значения функций на сервере и клиенте кажутся одинаковыми.   -  person Sivaram Kannan    schedule 07.06.2012
comment
Каково значение m_dwWriteBytes? Чтобы получить MD5 того, что вернула функция compress(), значение m_dwWriteBytes должно быть равно destLen + 525.   -  person Mark Adler    schedule 07.06.2012
comment
Обратите внимание, что это происходит не со всеми отправляемыми мной пакетами, а только с определенными пакетами. И, насколько я мог видеть, корреляции в размерах пакетов нет.   -  person Sivaram Kannan    schedule 07.06.2012
comment
Вы правы, m_dwWriteBytes равно destLen+525. В коде отсутствуют некоторые операторы, где я заполняю m_pWriteBuffer и на самом деле заполняю m_dwWriteBytes — я пропустил это для простоты.   -  person Sivaram Kannan    schedule 07.06.2012
comment
Нет смысла публиковать код, если вы удаляете строки посередине. Тогда нет возможности увидеть, что происходит, и, возможно, найти проблему. Пожалуйста, отредактируйте вопрос, чтобы включить полный код в соответствующие части.   -  person Mark Adler    schedule 07.06.2012
comment
Последовательность сжатия и распаковки буфера в приведенном выше коде верна.   -  person Sivaram Kannan    schedule 07.06.2012


Ответы (3)


Я также недавно столкнулся с этой проблемой, когда использовал zlib для сжатия/распаковки в памяти. Код выглядит следующим образом:

size_t size = 1048576;
void *data;
void *comp_data;
uLong comp_data_len;
void *uncomp_data;
uLong uncomp_data_len;
void *temp;
int ret;

data = calloc(1, size); // data is filled with all zeros

comp_data_len = size * 1.01 + 12;
comp_data = calloc(1, size);
ret = compress(comp_data, &comp_data_len, data, size); //here ret is Z_OK.

uncomp_data_len = size;
uncomp_data = calloc(1, uncomp_data_len);
ret = uncompress(uncomp_data, &uncomp_data_len, comp_data, comp_data_len); //here ret is Z_OK

temp = calloc(1, 496);

for (i = 0; i < 100; i++)
{
    //here fill some random data to temp

    memcpy((char*)data + i * 100, temp, 496);

    ret = compress(comp_data, &comp_data_len, data, size); //here ret is Z_OK.
    ret = uncompress(uncomp_data, &uncomp_data_len, comp_data, comp_data_len); //here ret sometimes is Z_OK, sometimes is Z_DATA_ERROR!!!
}

Я также проследил код и обнаружил, что он не работает и с оператором «inflate() function, (ZSWAP32(hold)) != state->check)». Поэтому я не могу поверить, что функция uncompress связана с шаблоном данных. Я ошибся?

Я также заметил, что функция сжатия вызывает deflate для сжатия, deflate обрабатывает данные каждые 64 КБ, поэтому нужно ли мне разбивать их на блоки по 64 КБ, сжимать каждый блок один за другим, а затем распаковывать может работать хорошо?

person GWF    schedule 05.06.2013

я не знаю, правильный ли это ответ, может быть, это поможет! мой английский очень плохой, надеюсь, вы понимаете. возможно параметры преобразования в другой имеет ошибки. когда они конвертируют информацию, возможно, теряют! я столкнулся с той же проблемой, после использования типа исходного кода проблема была решена (Bytef\uLongf\uLong и т. д.). ср китайский вы можете использовать Google для перевода. http://www.360doc.com/content/13/0927/18/11217914_317498849.shtml

person demon    schedule 27.09.2013

Это мой тест. Массив [] может быть больше, в то же время будут изменены sour[]/dest[]/destLen/Len. Используя тип исходного кода, проблема была решена. Надеюсь будет полезно.

мой код следующим образом:

    #include <stdio.h>
    #include "zlib.h"

    int main(){
        //the buffer can be larger
    Bytef arry[] = "中文测试 yesaaaaa bbbbb ccccc ddddd 中文测试 yesaaaaa bbbbb ccccc ddddd 中文测试yesaaaaa bbbbb ccccc ddddd 中文测试 yes 我是一名军人!";
    //buffer length
        int size = sizeof(arry);
    //store the uncompressed data
        Bytef sour[2500];
        //store the compressed data
    Bytef dest[2500];
        //压缩后的数据可能比源数据要大
    unsigned long destLen = 2500;
        //解压数据时因为不知道源数据大小,设置时长度尽可能大一些。以免出错
    unsigned long Len = 2500;
    int ret = -1;
    ret = compress(dest,&destLen,arry,size);
    //dest[destLen] = '\0';
    printf("ret = %d\ndest = %s\n", ret, dest);
    ret = uncompress(sour,&Len,dest,destLen);
    //sour[size-1] = '\0';
    printf("ret = %d\nsour = %s\n", ret, sour);
    return 0;
}
person demon    schedule 30.09.2013