【问题标题】:Chunked Stream Responds Incorrectly分块流响应不正确
【发布时间】:2019-02-14 06:47:47
【问题描述】:

对不起,标题这么模糊,我真的不知道这个问题的标题是什么。 基本上,当我得到传输编码所告诉的分块流时,我会执行以下代码:

private IEnumerable<byte[]> ReceiveMessageBodyChunked() {
    readChunk:
    #region Read a line from the Stream which should be a Block Length (Chunk Body Length)
    string blockLength = _receiverHelper.ReadLine();
    #endregion
    #region If the end of the block is reached, re-read from the stream
    if (blockLength == Http.NewLine) {
        goto readChunk;
    }
    #endregion
    #region Trim it so it should end up with JUST the number
    blockLength = blockLength.Trim(' ', '\r', '\n');
    #endregion
    #region If the end of the message body is reached
    if (blockLength == string.Empty) {
        yield break;
    }
    #endregion
    int blockLengthInt = 0;
    #region Convert the Block Length String to an Int32 base16 (hex)
    try {
        blockLengthInt = Convert.ToInt32(blockLength, 16);
    } catch (Exception ex) {
        if (ex is FormatException || ex is OverflowException) {
            throw new Exception(string.Format(ExceptionValues.HttpException_WrongChunkedBlockLength, blockLength), ex);
        }
        throw;
    }
    #endregion
    // If the end of the message body is reached.
    if (blockLengthInt == 0) {
        yield break;
    }
    byte[] buffer = new byte[blockLengthInt];
    int totalBytesRead = 0;
    while (totalBytesRead != blockLengthInt) {
        int length = blockLengthInt - totalBytesRead;
        int bytesRead = _receiverHelper.HasData ? _receiverHelper.Read(buffer, 0, length) : _request.ClientStream.Read(buffer, 0, length);
        if (bytesRead == 0) {
            WaitData();
            continue;
        }
        totalBytesRead += bytesRead;
        System.Windows.Forms.MessageBox.Show("Chunk Length: " + blockLengthInt + "\nBytes Read/Total:" + bytesRead + "/" + totalBytesRead + "\n\n" + Encoding.ASCII.GetString(buffer));
        yield return buffer;
    }
    goto readChunk;
}

这样做是从流中读取应该是块长度的 1 行数据,在这里和那里进行一些检查,但最终将其转换为 Int32 Radix16 整数。

从那里它基本上创建了一个 int32 的字节缓冲区作为它的长度大小。

然后它继续从流中读取,直到它读取到与我们转换的 Int32 相同的数量。

这很好用,但是,无论出于何种原因,它在最后一次读取时响应不正确。

它将读取确切的字节数,因为块长度非常好,并且我期望的所有数据都被读取。但是它还再次读取了另一小块数据,这些数据已经在最后读取,导致我们说从&lt;!DOCTYPE html&gt;&lt;/html&gt; ASWELL 的所有数据作为来自内部某处的一些数据,例如&lt;form&gt; e.t.c

这是发生的一个例子:

如您所见,不应该从阅读中返回突出显示的红色文本!它应该在&lt;/html&gt; 结束。 为什么 Chunk's Length 对我说谎,我怎样才能找到合适的尺寸来阅读?

【问题讨论】:

  • 如果有人想对此进行测试并且知道如何为此测试手动获取流设置,请针对始终需要 cloudflare 块检查的任何网站进行测试。 Cloudflares 块始终是传输编码的块响应
  • "...针对任何总是需要 cloudflare 块检查的网站进行测试..." - 所以您希望所有想帮助您的人首先找到这样的网站?或者您能否提供一个您看到此错误的实际 URL?
  • @SteffenUllrich torrentleech.org
  • 奇怪的是,如果我将请求交给另一个 TCPStream 代理(127.0.0.1:8888 作为代理,它是提琴手),它工作得很好......

标签: c# tcp stream chunked


【解决方案1】:

我不熟悉 C#,但如果我正确理解您的代码和 C# 中 Read 的语义(这似乎类似于 C 中的 read),那么问题是您使用的是相同的缓冲区一次又一次地没有先重置它:

byte[] buffer = new byte[blockLengthInt];
int totalBytesRead = 0;
while (totalBytesRead != blockLengthInt) {
    int length = blockLengthInt - totalBytesRead;
    int bytesRead = _receiverHelper.HasData ? _receiverHelper.Read(buffer, 0, length) : _request.ClientStream.Read(buffer, 0, length);
    ...
    totalBytesRead += bytesRead;
    ...
    yield return buffer;
}

举个例子说明这里出了什么问题:假设块大小是 10,你读取的内容是0123456789,第一次读取将返回 6 个字节,第二次读取剩余的 4 个字节。在这种情况下,您的缓冲区将在第一次读取后为012345,在第二次读取后为567845。缓冲区末尾的这些45 保留了先前读取的内容,因为您只替换了缓冲区中的前 4 个字节,但保留了其余字节。

奇怪的是,如果我将请求交给另一个 TCPStream 代理(127.0.0.1:8888 作为代理,它是提琴手)它工作得非常好......

Fiddler 是一个代理,可能会改变响应的传输方式。例如,它可能使用Content-length 而不是分块编码,或者它可能使用较小的块,以便您始终在第一次读取时获得完整的块。

【讨论】:

  • OHHH 看了我的sn-p下的例子,我真的明白你的意思了!
  • 如果我正确理解了我的问题的原因,我应该将缓冲区声明移动到 while() 循环内部,这样它的重置就可以读取了吗?
  • 好吧真的很奇怪,但是当我对产生的返回进行搜索,并将它们附加到一个列表中,然后在我 mbox 时无论出于何种原因使用字节 [] 的 Encoding.ASCII.GetString() 进行转换它查看文本数据,它只显示第一个收益返回的内容,但它显示它具有适当的长度。什么?
  • 如果我转换为字符串并将其 mbox 作为它在 foreach 中的循环,它表明它正在经历所有产量,但是在 foreach 之后,当我获取所有列表内容并显示它时,它会失败,好像 .read 在末尾放了一个奇怪的破碎字符,导致它完全破坏了东西
  • 在启用了显示所有字符的 Notepad++ 中,查看 CR/LF 等,我看到的只是 CR/LF 没有别的(当然除了实际的文本)。所以也许 CR/LF 对 MBOX 很奇怪?但它也很奇怪,因为如果我 clipboard.settext 它,它会做同样的事情,在第一次读取结束时切断
猜你喜欢
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
相关资源
最近更新 更多