首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在.net核心中创建“共享zlib上下文”

在.net核心中创建“共享zlib上下文”
EN

Stack Overflow用户
提问于 2021-02-07 15:07:17
回答 2查看 370关注 0票数 1

我正试图为这个不和谐的API构建一个WebSocket客户端,作为一个有趣的附带项目,但是我遇到了一个我目前似乎无法解决的问题。

https://discord.com/developers/docs/topics/gateway#encoding-and-compression

在关于如何解压缩从API返回的输入数据的示例中,他们说:

传输压缩:当前唯一可用的传输压缩选项是zlib-stream。您需要通过共享的zlib上下文运行所有接收到的数据包,如下面的示例所示。每个到网关的连接都应该使用自己独特的zlib上下文。

我第一次对来自它们的响应进行解压缩(比如在一个连接中)的工作就像预期的那样,但是第二次给出了一个错误,说“未知压缩方法”。

我假设这是因为我为解压缩第一个响应而实例化的部分需要为这个连接的未来响应(只是脱离他们的文档所描述的)而持续存在,但我不知道这在C#中对于我正在使用的内容到底意味着什么。

代码语言:javascript
复制
static byte[] Decompress(byte[] data)
{
    using var compressedStream = new System.IO.MemoryStream(data);
    using var zipStream = new ZlibStream(compressedStream, CompressionMode.Decompress);
    using var resultStream = new System.IO.MemoryStream();
    zipStream.CopyTo(resultStream);
    return resultStream.ToArray();
}

下面是我用于解压缩的方法,ZlibStream来自Ionic.Zlib,但是使用他们的内置方法:"ZlibStream.UncompressString",似乎做同样的事情,也会产生同样的错误。

在这种情况下,“通过共享的zlib上下文运行所有接收到的数据包”到底意味着什么?在给定连接的所有解压缩任务中,是否存在某种高阶压缩上下文?还有别的吗?

谢谢事先,如果我可以澄清或添加任何额外的细节,让我知道!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-18 13:36:13

正如Mark所说,您需要按正确的顺序向充气器数据包提供信息。这使得它能够引用以前的字节,并可以使用它们来填补空白。

我已经成功地用Ionic.Zlib.ZlibCodec解决了这个问题,它使您能够更好地控制编解码器(这样它就不会在每次膨胀时都继续启动新的上下文)。

代码语言:javascript
复制
public class ZlibStreamContext
{
    private ZlibCodec _inflator;

    public ZlibStreamContext(bool expectRFC1950Header = false)
    {
        _inflator = new ZlibCodec();
        _inflator.InitializeInflate(expectRFC1950Header);
    }

    public byte[] InflateByteArray(byte[] deflatedBytes)
    {
        _inflator.InputBuffer = deflatedBytes;
        _inflator.AvailableBytesIn = deflatedBytes.Length;
        // account for a lot of possible size inflation (could be much larger than 4x)
        _inflator.OutputBuffer = new byte[deflatedBytes.Length * 4]; 
        _inflator.AvailableBytesOut = _inflator.OutputBuffer.Length;
        _inflator.NextIn = 0;
        _inflator.NextOut = 0;

        _inflator.Inflate(FlushType.Sync);
        return _inflator.OutputBuffer[0.._inflator.NextOut];
    }
}

我在缓冲区的末尾切掉了未使用的字节,但是如果要使用System.Text.Encoding.UTF8.GetString(byteArray),则不需要这样做。即使没有适当调整输出数组的大小,它也会工作。

注意:你需要砍掉头从第一包不和谐发送给你。或者,您可以将expectRFC1950Header设置为true,并将默认的头78 9c添加到每个数据包中(尽管我建议使用前者)。

票数 2
EN

Stack Overflow用户

发布于 2021-02-07 16:35:54

这意味着对于单个连接,您需要为整个连接保持打开的zlib解压缩对象,并继续按顺序向它提供数据包,直到连接完成为止。对每个数据包使用解压缩对象上的Write方法。

在连接完成的同时,zlib流还应该通知您数据已经完成,因为格式是自动终止的。此外,如果有任何数据被破坏,在结束时会有一个检查值报告错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66089413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档