gpt4 book ai didi

c# - BinaryReader.ReadChars() 问题

转载 作者:太空狗 更新时间:2023-10-29 20:29:33 25 4
gpt4 key购买 nike

我认为 BinaryReader.ReadChars() 方法存在问题。当我在原始套接字 NetworkStream 周围包装 BinaryReader 时,偶尔会出现流损坏,其中正在读取的流不同步。有问题的流包含二进制序列化协议(protocol)中的消息。

我已经追踪到以下内容

  • 仅在读取 unicode 字符串(使用 Encoding.BigEndian 编码)时发生
  • 只有当有问题的字符串被分成两个 tcp 数据包时才会发生(使用 wireshark 确认)

我认为发生的事情如下(在下面示例的上下文中)

  • 调用 BinaryReader.ReadChars() 要求它读取 3 个字符(字符串长度在字符串本身之前编码)
  • 第一个循环在内部请求从网络流中读取 6 个字节(剩余 3 个字符 * 2 个字节/字符)
  • 网络流只有3个字节可用
  • 3 个字节读入本地缓冲区
  • 缓冲区交给解码器
  • 解码器解码 1 个字符,并将另一个字节保存在它自己的内部缓冲区中
  • 第二个循环内部请求读取 4 个字节! (2 个剩余字符 * 2 个字节/字符)
  • 网络流有全部 4 个字节可用
  • 4 个字节读入本地缓冲区
  • 缓冲区交给解码器
  • 解码器解码2个字符,并在内部保留剩余的第4个字节
  • 字符串解码完成
  • 序列化代码尝试解码下一个项目,但由于流损坏而崩溃。

    char[] buffer = new char[3];
    int charIndex = 0;

    Decoder decoder = Encoding.BigEndianUnicode.GetDecoder();

    // pretend 3 of the 6 bytes arrives in one packet
    byte[] b1 = new byte[] { 0, 83, 0 };
    int charsRead = decoder.GetChars(b1, 0, 3, buffer, charIndex);
    charIndex += charsRead;

    // pretend the remaining 3 bytes plus a final byte, for something unrelated,
    // arrive next
    byte[] b2 = new byte[] { 71, 0, 114, 3 };
    charsRead = decoder.GetChars(b2, 0, 4, buffer, charIndex);
    charIndex += charsRead;

我认为根源是 .NET 代码中的一个错误,它使用 charsRemaining * bytes/char 每个循环来计算所需的剩余字节数。由于隐藏在解码器中的额外字节,此计算可能会关闭一个,从而导致从输入流中消耗额外的字节。

这是有问题的 .NET 框架代码

    while (charsRemaining>0) { 
// We really want to know what the minimum number of bytes per char
// is for our encoding. Otherwise for UnicodeEncoding we'd have to
// do ~1+log(n) reads to read n characters.
numBytes = charsRemaining;
if (m_2BytesPerChar)
numBytes <<= 1;

numBytes = m_stream.Read(m_charBytes, 0, numBytes);
if (numBytes==0) {
return (count - charsRemaining);
}
charsRead = m_decoder.GetChars(m_charBytes, 0, numBytes, buffer, index);

charsRemaining -= charsRead;
index+=charsRead;
}

我不完全确定这是一个错误还是 API 的滥用。为了解决这个问题,我只是自己计算所需的字节,读取它们,然后通过相关的 Encoding.GetString() 运行 byte[]。然而,这不适用于像 UTF-8 这样的东西。

有兴趣听听人们对此的想法以及我是否做错了什么。也许它会为下一个人节省几个小时/几天的繁琐调试。

编辑:发布连接Connect tracking item

最佳答案

我已经用 BinaryReader.ReadChars 重现了你提到的问题。

虽然开发人员在编写流和解码器之类的东西时总是需要考虑先行,但这似乎是 BinaryReader 中的一个相当严重的错误,因为该类旨在读取由各种类型的数据结构组成的数据结构数据。在这种情况下,我同意 ReadChars 在读取内容时应该更加保守以避免丢失该字节。

直接使用 Decoder 的解决方法没有任何问题,毕竟那是 ReadChars 在幕后所做的。

Unicode 是一个简单的例子。如果您考虑任意编码,当您传入字符数而不是字节数时,确实没有通用的方法来确保消耗正确的字节数(考虑不同长度的字符和涉及格式错误的输入的情况)。出于这个原因,避免 BinaryReader.ReadChars 以读取特定字节数提供了更强大的通用解决方案。

我建议您通过 http://connect.microsoft.com/visualstudio 将此事提请微软注意。 .

关于c# - BinaryReader.ReadChars() 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1804433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com