Действительно, вы не получаете чанкинг, но контент чанкован.Вы должны нарисовать для себя, как может выглядеть любой полученный вами буфер.Это не так, как вы получаете один кусок в то время.Иногда у вас есть некоторые данные предыдущего чанка, строка, указывающая размер нового чанка, сопровождаемая некоторыми данными чанка.Как-то в другой раз вы просто получаете немного данных чанка.В другой раз немного данных чанка и часть строки, указывающая новый чанк и т. Д., И т. Д. Представьте себе худшие сценарии, это не легко.Прочитайте это: http://www.jmarshall.com/easy/http/
Прежде чем вы сможете использовать следующий фрагмент кода, получите все заголовки до пустой строки.Где содержимое начинается в буфере nContentStart
.Код использует некоторые внутренние классы, которыми я не могу поделиться, но вы должны понять;) Насколько я тестировал, он работает как ожидалось и не теряет память.Хотя, поскольку это не легко, я не могу быть полностью уверен!
if (bChunked)
{
int nOffset = nContentStart;
int nChunkLen = 0;
int nCopyLen;
while (true)
{
if (nOffset >= nDataLen)
{pData->SetSize(0); Close(); ASSERTRETURN(false);}
// copy data of previous chunk to caller's buffer
if (nChunkLen > 0)
{
nCopyLen = min(nChunkLen, nDataLen - nOffset);
n = pData->GetSize();
pData->SetSize(n + nCopyLen);
memcpy(pData->GetPtr() + n, buf.GetPtr() + nOffset, nCopyLen);
nChunkLen -= nCopyLen;
ASSERT(nChunkLen >= 0);
nOffset += nCopyLen;
if (nChunkLen == 0)
nOffset += strlen(lpszLineBreak);
ASSERT(nOffset <= nDataLen);
}
// when previous chunk is copied completely, process new chunk
if (nChunkLen == 0 && nOffset < nDataLen)
{
// chunk length is specified on first line
p1 = buf.GetPtr() + nOffset;
p2 = strstr(p1, lpszLineBreak);
while (!p2) // if we can't find the line break receive more data until we do
{
buf.SetSize(nDataLen + RECEIVE_BUFFER_SIZE + 1);
nReceived = m_socket.Receive((BYTE*)buf.GetPtr() + nDataLen, RECEIVE_BUFFER_SIZE);
if (nReceived == -1)
{pData->SetSize(0); Close(); ASSERTRETURN(false);} // connection error
if (nReceived == 0)
{pData->SetSize(0); Close(); ASSERTRETURN(false);} // all data already received but did not find line break
nDataLen += nReceived;
buf[nDataLen] = 0;
p1 = buf.GetPtr() + nOffset; // address of buffer likely changed
p2 = strstr(p1, lpszLineBreak);
}
*p2 = 0;
p2 += strlen(lpszLineBreak);
p3 = strchr(p1, ';');
if (p3)
*p3 = 0;
if (sscanf(p1, "%X", &nChunkLen) != 1)
{pData->SetSize(0); Close(); ASSERTRETURN(false);}
if (nChunkLen < 0)
{pData->SetSize(0); Close(); ASSERTRETURN(false);}
if (nChunkLen == 0)
break; // last chunk received
// copy the following chunk data to caller's buffer
nCopyLen = min(nChunkLen, buf.GetPtr() + nDataLen - p2);
n = pData->GetSize();
pData->SetSize(n + nCopyLen);
memcpy(pData->GetPtr() + n, p2, nCopyLen);
nChunkLen -= nCopyLen;
ASSERT(nChunkLen >= 0);
nOffset = (p2 - buf.GetPtr()) + nCopyLen;
if (nChunkLen == 0)
nOffset += strlen(lpszLineBreak);
if (nChunkLen == 0 && nOffset < nDataLen)
continue; // a new chunk starts in this buffer at nOffset, no need to receive more data
}
// receive more data
buf.SetSize(RECEIVE_BUFFER_SIZE + 1);
nDataLen = m_socket.Receive((BYTE*)buf.GetPtr(), RECEIVE_BUFFER_SIZE);
if (nDataLen == -1)
{pData->SetSize(0); Close(); ASSERTRETURN(false);}
if (nDataLen == 0)
{pData->SetSize(0); Close(); ASSERTRETURN(false);}
buf[nDataLen] = 0;
nOffset = 0;
}
// TODO: receive optional footers and add them to m_headers
}