分块流响应不正确

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


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;

        if (bytesRead == 0) {

            WaitData();

            continue;

        }

        totalBytesRead += bytesRead;

        yield return buffer;

    }

    goto readChunk;

}

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


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


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


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


它将读取确切的字节数,因为块长度非常好,并且我期望的所有数据都被读取。但它也在再次读取另一小块数据,这些数据在最后已经读取,导致我们可以说从ASWELL<!DOCTYPE html>到</html>ASWELL 的所有数据作为来自内部某处的一些数据<form>等


这是发生的事情的一个例子:

http://img2.mukewang.com/61da9d3a0001bce404070652.jpg

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


眼眸繁星
浏览 194回答 1
1回答

一只萌萌小番薯

我不熟悉 C# 但如果我正确理解了您的代码和ReadC# 中的语义(这似乎与readC 中的相似),那么问题是您一次又一次地使用相同的缓冲区而没有先重置它:byte[] buffer = new byte[blockLengthInt];int totalBytesRead = 0;while (totalBytesRead != blockLengthInt) {&nbsp; &nbsp; int length = blockLengthInt - totalBytesRead;&nbsp; &nbsp; int bytesRead = _receiverHelper.HasData ? _receiverHelper.Read(buffer, 0, length) : _request.ClientStream.Read(buffer, 0, length);&nbsp; &nbsp; ...&nbsp; &nbsp; totalBytesRead += bytesRead;&nbsp; &nbsp; ...&nbsp; &nbsp; yield return buffer;}举例说明这里出了什么问题:假设块大小为 10,您读取的内容是0123456789,第一次读取将返回 6 个字节,第二次读取剩余的 4 个字节。在这种情况下,您的缓冲区将012345在第一次读取567845之后和第二次读取之后。这些45在缓冲区末尾量与上一读,因为你只是取代了缓冲区中的第4个字节,但保留了休息。奇怪的是,如果我将请求交给另一个 TCPStream 代理(127.0.0.1:8888 作为代理,它是提琴手),它工作得非常好......Fiddler 是一个代理,可能会改变响应的传输方式。例如,它可能使用Content-length分块编码而不是分块编码,或者它可能使用较小的块,以便您始终在第一次读取时获得完整的块。
打开App,查看更多内容
随时随地看视频慕课网APP