创建“共享的zlib上下文".在.net核心中 [英] Creating a "shared zlib context" in .net core

查看:79
本文介绍了创建“共享的zlib上下文".在.net核心中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为Discord API构建一个WebSocket客户端,作为一个有趣的项目,但遇到了一个当前似乎无法解决的问题.

I'm trying to build a WebSocket client for the Discord API as a fun side project, but I've run into an issue that I can't seem to resolve currently.

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

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

In their example for how to decompress input data returned from their API, they say:

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

Transport Compression: Currently the only available transport compression option is zlib-stream. You will need to run all received packets through a shared zlib context, as seen in the example below. Every connection to the gateway should use its own unique zlib context.

我第一次解压缩来自它们的响应(就像在一个连接中一样),但是第二次却给了我一个错误,说未知的压缩方法".

My first time decompressing a response from them (as in for one connection) works as expected, but the second time gives me an error saying "unknown compression method".

我假设这是因为我要解压缩第一个响应的实例化的一部分需要为该连接的将来响应而持久化(只是脱离了他们文档中所说的),但是我不确定这实际上意味着我正在使用C#.

I'm assuming that this is because some portion of what I'm instantiating to decompress the first response needs to persist for future responses for this connection (just going off what their documentation says), but I'm not sure what that actually means in C# for what I'm using.

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",似乎在做同样的事情,也会产生相同的错误.

Here is the method I'm using for decompression, ZlibStream comes from Ionic.Zlib, however using their built-in method: "ZlibStream.UncompressString", which seems to do the same thing, also produces the same error.

通过共享的zlib上下文运行所有接收到的数据包"到底是什么意思?在这种情况下?对于给定的连接,我是否需要在所有解压缩任务中保留一些更高阶的压缩上下文?还有吗?

What exactly would it mean to "run all received packets through a shared zlib context" in this situation? Is there some higher order compression context that I need to persist across all decompression tasks for a given connection? Something else?

在此先感谢您能否澄清或添加其他详细信息!

Thanks in advance, let me know if I can clarify or add any additional details!

推荐答案

正如Mark Adler所说,您需要以正确的顺序送入充气机数据包.这样便可以引用前面的字节,并可以使用它们来填补空白.

As Mark Adler said, you need to feed the inflator packets in the right order. This is so that it has reference to the previous bytes and can use them to fill in the gaps.

我已经设法使用 Ionic.Zlib.ZlibCodec 解决了这个问题,它为您提供了对编解码器的更多控制(这样,您每次膨胀时就不会一直启动新的上下文)./p>

I've managed to solve this using Ionic.Zlib.ZlibCodec which gives you more control over the codec (so that it doesn't keep starting a new context every time you inflate).

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).即使没有正确调整输出数组的大小,它也可以工作.

I chop off the unused bytes in the buffer at the end there, but you don't need to if you're just going to use System.Text.Encoding.UTF8.GetString(byteArray). It will work even without properly sizing the output array.

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

Note: You need to chop off the header from the first packet discord sends you. Or you can set expectRFC1950Header to true and add the default header 78 9c to each of the packets (though I'd recommend the former).

这篇关于创建“共享的zlib上下文".在.net核心中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆