I'm having trouble reading in some chunked HTTP response data using winsock. I send a request fine and get the following back:
HTTP/1.1 200 OK
Server: LMAX/1.0
Content-Type: text/xml; charset=utf-8
Transfer-Encoding: chunked
Date: Mon, 29 Aug 2011 16:22:19 GMT
using winsock recv. At this point however it just hangs. I have the listener running in an infinite loop but nothing is ever picked up.
I think it's a C++ issue but it could also be related to the fact that I pushing the connection through stunnel to wrap it up inside HTTPS. I have a test application using some libs in C# which works perfectly through stunnel. I'm confused as to why my loop is not receiving the C++ chunked data after the initial recv.
This is the loop in question...it is called after the chunked ok response above...
while(true)
{
recvBuf= (char*)calloc(DEFAULT_BUFLEN, sizeof(char));
iRes = recv(ConnectSocket, recvBuf, DEFAULT_BUFLEN, 0);
cout << WSAGetLastError() << endl;
cout << "Recv: " << recvBuf << endl;
if (iRes==SOCKET_ERROR)
{
cout << recvBuf << endl;
err = WSAGetLastError();
wprintf(L"WSARecv failed with error: %d\n", err);
break;
}
}
Any ideas?
Indeed you do not receive chunked, but the content is chunked. You have to draw a picture for yourself how any buffer you receive might look. It's not like you receive one chunk at the time. Sometimes you have some data of the previous chunk, the line indicating the size of the new chunk, followed by some chunk data. Some other time you just receive just a bit of chunk data. Another time a bit of chunk data and a part of the line indicating the new chunk, etc, etc. Imagine the worst case scenarios, this isn't easy. Read this: http://www.jmarshall.com/easy/http/
Before you can use the following piece of code receive all the headers until the empty line. Where the content starts in the buffer is
nContentStart
. The code uses some in-house classes I cannot share but you should get the idea ;) As far as I tested it works like expected and does not leak memory. Although since this isn't easy I cannot be completely sure!You need to change your reading code. You cannot read
chunked
data using a fixed-length buffer like you are trying to do. The data is sent in variable-length chunks, where each chunk has a header that specifies the actual length of the chunk in bytes, and the final chunk of the data has a length of 0. You need to read the chunked headers in order to process the chunks properly. Please read RFC 2616 Section 3.6.1. Your logic needs to be more like the following pseudo-code: