Chunked Stream响应不正确
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Chunked Stream响应不正确相关的知识,希望对你有一定的参考价值。
对于这样一个模糊的标题,我真的不知道该怎么称呼这个问题。基本上当我得到一个按照Transfer-Encoding告知的流分块时,我会执行以下代码:
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(' ', '
', '
');
#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 + "
Bytes Read/Total:" + bytesRead + "/" + totalBytesRead + "
" + Encoding.ASCII.GetString(buffer));
yield return buffer;
}
goto readChunk;
}
这样做是从流中读取1行数据,这应该是Chunk的长度,在这里和那里进行一些检查,但最终将其转换为Int32 Radix16整数。
从那里它实际上创建了一个int32的字节缓冲区作为其长度大小。
然后它继续从流中读取,直到它读取与我们转换的Int32相同的量。
然而,无论出于何种原因,它的效果都非常出色,它在最后一次阅读中的反应不正确。
它将读取精确的字节数,因为块长度完全正常,并且我期望的所有数据都被读取。但它还是再次读取另一小部分数据,这些数据最后已被读取,导致让我们说从<!DOCTYPE html>
到</html>
ASWELL的所有数据都是来自某些地方的数据,如<form>
e.t.c
这是发生的事情的一个例子:
如您所见,突出显示的红色文本不应该从读取中返回!它应该在</html>
结束。为什么Chunk的长度对我来说,我怎样才能找到合适的尺寸来阅读?
我不熟悉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个字节,但保留了其余部分。
什么奇怪的AF是如果我把请求交给另一个代理的TCPStream(127.0.0.1:8888作为代理人,这是一个小提琴手)它完全正常......
Fiddler是一个代理,可能会改变响应的传输方式。例如,它可能使用Content-length
而不是chunked编码,或者它可能使用较小的块,以便您始终在第一次读取时获得完整的块。
以上是关于Chunked Stream响应不正确的主要内容,如果未能解决你的问题,请参考以下文章
HTTP协议扫盲(九 )HTTP1.1响应的Transfer-Encoding=chunked方式
如何修复“HTTP 标头中 CRLF 序列的不正确中和('HTTP 响应拆分')”