我有一对使用网络流进行通信的 C# 客户端-服务器程序。一切正常,因为它没有压缩。现在我想降低带宽使用率,所以我想在我的网络流周围使用压缩包装流。
我已经尝试过 SharpZipLib、DotNetZip、C# 自己的 GZipStream——但我无法让它们中的任何一个工作。
SharpZipLib 有刷新问题,并应用此处指定的修复:http: //community.sharpdevelop.net/forums/p/7855/22139.aspx导致异常“标题校验和非法”。
使用 DotNetZip 的 DeflateStream 会导致 ZLibException("Bad state (invalid stored block lengths)");
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();
并通过再次调用 CreateInputStreamWrapper 立即创建一个新的 inputStream。
发生什么了 ?由于所有压缩流实现都失败,错误归结为“数据流中有错误”,我有一种预感,一定是我和我的代码。另一方面,如果我删除压缩并只使用网络流就没有问题,这让我认为问题一定出在压缩代码上。
这听起来很熟悉吗?当我们在做的时候,有没有人知道任何(其他)适合环绕网络流的压缩流实现?