Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unusual HTTP Response in Basic C++ Socket Programming

Tags:

c++

c

http

sockets

I've got a basic HTTP client set up in C++, which works ok so far. It's for a school assignment, so there's lots more to do, but I'm having a problem.

I use the recv() function in a while loop, to repeatedly add pieces of the response to my response buffer, and then output that buffer each time. The problem is, at the end of each piece of the response, the HTTP Request is getting tacked on as well.

For example, the response will be a chunk of the page's source code, followed by "GET / HTTP/1.1...", followed by the next chunk, and then the "GET..." again, and so on.

Here's my relevant code:

 // Prepare request
char request[] = "HEAD /index.html HTTP/1.1\r\nHOST: www.google.com\r\nCONNECTION: close\r\n\r\n";

// Send request
len = send(sockfd, request, sizeof(request), 0);

// Write/output response
while (recv(sockfd, buf, sizeof(buf), 0) != 0)
{
    // Read & output response
    printf("%s", buf);
}
like image 768
Ishmael Smyrnow Avatar asked Mar 01 '23 04:03

Ishmael Smyrnow


2 Answers

The buffer isn't null terminated, which is required for strings in C++. When you see the "extra GET", you are seeing memory that you shouldn't be because the stdlib tried to print your buffer, but never found a '\0' character.

A quick fix is to force the buffer to be terminated:

int n = 1;
while (n > 0) {
    n = recv(sockfd, buf, sizeof(buf), 0);
    if (n > 0) {
        // null terminate the buffer so that we can print it
        buf[n] = '\0';

        // output response
        printf("%s", buf);
    }
}
like image 167
Frank Krueger Avatar answered Mar 06 '23 21:03

Frank Krueger


I suspect it's because your buf is allocated in memory just below your request. When you call printf on the buffer, printf will print as much as it can before finding a NUL character (which marks the end of the string). If there isn't one, it'll go right on through into request. And generally, there won't be one, because recv is for receiving binary data and doesn't know that you want to treat its output a string.

One quick fix would be to limit the receive operation to sizeof(buf)-1, and to explicitly add the NUL terminator yourself, using the size of the returned data:

while ((nr = recv(sockfd, buf, sizeof(buf), 0)) > 0)
{
    buf[nr] = 0;
    ...
}

Of course, for this to (marginally) safe you need to be sure that you'll always receive printable data.

like image 42
Edmund Avatar answered Mar 06 '23 21:03

Edmund