C # сжатие сетевого потока - Sharpziplib, DotNetZip, gzipstream все выдают ошибки в моем потоке - PullRequest
2 голосов
/ 12 марта 2012

У меня есть пара клиент-серверных программ на C #, которые общаются с помощью сетевого потока.Все работает нормально, как и без сжатия.Теперь я хотел бы уменьшить использование полосы пропускания, поэтому я хочу использовать сжатую обертку вокруг моего сетевого потока.

Я пробовал SharpZipLib, DotNetZip, собственный CZ GZipStream - но я не могу заставить ни одного из нихwork.

SharpZipLib имеет проблемы с сбросом, и применение указанного здесь исправления: http://community.sharpdevelop.net/forums/p/7855/22139.aspx приводит к исключению "Контрольная сумма заголовка недопустима".

Использование DlateNetZip DeflateStream приводит к исключению ZLibException («Плохое состояние (недопустимая длина хранимых блоков)»);

GZipStream дает мне исключение System.IO.InvalidDataException, в котором говорится «Магическое число в заголовке GZip неверно. Убедитесь, что вы передаете поток GZip»..

Способ, который я реализовал, заключается в том, что каждый раз, когда моя инфраструктура должна отправлять массив байтов, я создаю новую оболочку потока сжатия вокруг существующего сетевого потока, записываю байты в поток сжатия изатем промойте, закройте и утилизируйте его.Это сделано для того, чтобы каждый WriteMessage (byte [] blah) использовал свой собственный независимый от состояния поток сжатия, который будет немедленно очищен.Я позаботился о том, чтобы ни один из потоков не закрывал исходный сетевой поток.

                using (System.IO.Stream outputStream = CreateOutputStreamWrapper(_networkStream))
                {
                    outputStream.Write(messageBytes, 0, messageBytes.Length);
                    outputStream.Flush();
                    outputStream.Close();
                    outputStream.Dispose();
                }

По сути, мой DecompressionStream создается следующим образом (необязательные комментарии)

protected System.IO.Stream CreateInputStreamWrapper(System.IO.Stream inInputStream)
{
        //return new DeflateStream(inInputStream, CompressionMode.Decompress, true);
        //return new BZip2InputStream(inInputStream, true);
        return new GZipStream(inInputStream, System.IO.Compression.CompressionMode.Decompress, true);
}

иначинается как

_inputStream.BeginRead(_buffer, 0, _buffer.Length, new AsyncCallback(ReceiveCallback), null);

, затем в ReceiveCallback данные читаются, поток сбрасывается, закрывается и удаляется:

            //Get received bytes count
            var bytesRead = _inputStream.EndRead(ar);
            _inputStream.Flush();
            _inputStream.Close();
            _inputStream.Dispose();

и немедленно создает новый inputStream, снова вызывая CreateInputStreamWrapper.

Так что же происходит?Так как все реализации потока сжатия терпят неудачу с ошибками, которые сводятся к «есть ошибка в потоке данных», у меня есть догадка, это должны быть я и мой код.С другой стороны, если я снимаю сжатие и просто использую сетевой поток, проблем нет, что заставляет меня думать, что проблема должна заключаться в коде сжатия.

Звучит ли это кому-нибудь знакомо?И в то время как мы находимся в этом, кто-нибудь знает о любых (других) реализациях потока сжатия, которые подходят для обтекания сетевого потока?

1 Ответ

4 голосов
/ 13 марта 2012

На всякий случай, если кто-нибудь когда-нибудь прочтет это, потоки ZLib DotNetZip имеют флаг FlushMode, который позволяет вам настроить совместимость с очисткой для сетевых устройств (режимы «Синхронизация» и «Полный»).

...