Извините за столь расплывчатое название, я действительно не знаю, как озаглавить этот выпуск.
В основном, когда я получаю поток, который разделен на части, как сказано в 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(' ', '\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;
}
То, что это делает, читает одну строку данных из потока, которая должна быть длиной блока, выполняет некоторые проверки здесь и там, но в конечном итоге преобразует это в целое число Int32 Radix16.
Оттуда он по существу создает байтовый буфер этого int32 как его размер длины.
Затем он просто продолжает читать из потока до тех пор, пока его чтение не станет таким же, как у преобразованного Int32.
Это работает великолепно, однако, по какой-то причине, он некорректно реагирует на последнее чтение.
Он будет считывать точное количество байтов, так как длина фрагмента отлично, и все данные, которые я ожидаю, читаются. НО это ТАКЖЕ читает еще один маленький кусок данных, который УЖЕ был прочитан в самом конце, в результате чего давайте скажем все данные от <!DOCTYPE html>
до </html>
ASWELL как некоторые данные изнутри где-то вроде <form>
e.t.c
Вот пример того, что произошло:
Как видите, выделенный красный текст НЕ должен был возвращаться из чтения! Это должно было закончиться в </html>
.
Почему длина куска лжет мне и как я могу найти правильный размер для чтения?