c# - Thrift 如何处理 Zlib 刷新标记被分割成多个消息?

标签 c# c++ thrift zlib

我有一个应用程序,它有一个 C++ 服务器和一个使用 Apache Thrift 的 C# 客户端。我用 TZlibTransport.cpp用于服务器上的 zlib 压缩,以及使用 Ionic.Zlib 解压缩客户端中的数据的包装器,这在大多数情况下都有效。

我注意到在非常特殊的情况下,客户端会因以下错误之一而崩溃:

Thrift.Protocol.TProtocolException: Missing version in readMessageBegin, old client?
   at Thrift.Protocol.TBinaryProtocol.ReadMessageBegin()

Ionic.Zlib.ZlibException: Bad state (invalid block type)
   at Ionic.Zlib.InflateManager.Inflate(FlushType flush)

我发现在发生这些错误的所有情况下,服务器都发送了两个包,一个刚刚超过 1024 字节(这是 TZlibTransport.cpp 使用的 compressed write buffer 的大小),另一个是 5- 8 个字节。看第二个包上的数据,发现是zlib用的flush marker,加了两次,

ff ff 00 00 00 ff ff

第一个标记的第一部分位于前一个包的末尾。如果我稍微增加缓冲区的大小,以便它有足够的空间在一个包中写入标记,则不会发生崩溃,所以我相信是这个标记被添加了两次导致了问题。然而,仅更改此缓冲区大小并不是解决方案,因为这意味着错误会发生在应用程序的其他地方。

我查看了 zlib,发现如果缓冲区中没有足够的空间 (https://github.com/madler/zlib/issues/149),这是预期的行为。然而,我还没有找到任何人遇到过这个导致 Thrift 问题的人。

因此,我的问题是,对于特定的数据长度,thrift 是否应该将标记拆分到多个包中,以及客户端应该如何处理这个问题。

最佳答案

看起来问题不在于标记被发射了两次,而只是第一个标记没有完全适合缓冲区。如果输出只是 ff ff,您将遇到完全相同的问题和相同的错误消息。 ff 无法启动 deflate 流,因为它提供了无效的 block 类型 (3)。

根据您的描述,Thrift 中似乎存在错误,因为它无法确保和/或检查所有压缩数据是否确实适合缓冲区。

关于c# - Thrift 如何处理 Zlib 刷新标记被分割成多个消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51784225/

相关文章:

c++ - 如何找到 InternetRegistry 用户 key 或父注册表 key

c++ - Visual Studio native 单元测试 : Debug/console output?

c# - 在 C# 中解码西里尔文 HTML 实体

c# - uint 中的按位移位

c# - FileUpload.PostedFile 始终为空,除非页面至少回发一次?

c++ - 奇怪的线程行为

rpc - 什么是 RPC 框架和 Apache Thrift?

c++ - 成功进行 SSL 通信的要求

c++ - Thrift 服务器 : detect client disconnections (C++ library)

c# - 异常处理中的设计模式