Matthew Scheffel
Matthew Scheffel

Reputation: 60

HTTP Server Not Sending Complete File To WGET, Firefox. Connection reset by peer?

I'm writing an HTTP server, and am having trouble sending larger files. If I grab them with netcat, the output seems perfect. If I use a browser or wget, I only get the complete file sometimes. WGET keeps getting "connection reset by peer" errors, see the output below. Firefox says "the connection was reset".

Here's the relevant procedure that sends data to the client:

int handle_request(int sockfd, struct cached_file content) {
    char buffer[1024]; // FIXME hardcoded arbitrary buffer size for header

    unsigned int sent_bytes;
    unsigned int total = 0;
    unsigned int bytes_left = content.size;

    printf("I have to send %u bytes of content.\n", content.size);

    snprintf(buffer, 1024, "HTTP/1.1 %s\nContent-Type: %s\nContent-Length: %s\n\n", content.statuscode, content.contenttype, content.sizestring);
    sent_bytes = send(sockfd, buffer, strlen(buffer), MSG_MORE);
    printf("I wanted to send %u bytes of header, and I sent %u.\n", strlen(buffer), sent_bytes);

    while (total < bytes_left) {
        sent_bytes = send(sockfd, content.data+total, bytes_left, 0);
        if (sent_bytes == -1) { 
            printf("send() returned -1\n");
            break; 
        }

        total      += sent_bytes;
        bytes_left -= sent_bytes;
    }
    printf("I sent %u bytes of content. I had %u left to send.\n", total, bytes_left);

    if (sent_bytes == -1)
        logprint("socket error!", errno);
}

Here's the output from wget trying to grab the file:

wget --tries 1 http://localhost:8081/image.jpg
--2015-07-01 13:21:42--  http://localhost:8081/image.jpg
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8081... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:8081... connected.
HTTP request sent, awaiting response... 200 OK
Length: 700895 (684K) [image/jpeg]
Saving to: ‘image.jpg.10’

image.jpg.10                      53%[===============================>                             ] 363.31K  --.-KB/s   in 0.001s 

2015-07-01 13:21:42 (688 MB/s) - Read error at byte 372031/700895 (Connection reset by peer). Giving up.

wget --tries 1 http://localhost:8081/image.jpg
--2015-07-01 13:21:43--  http://localhost:8081/image.jpg
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:8081... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:8081... connected.
HTTP request sent, awaiting response... 200 OK
Length: 700895 (684K) [image/jpeg]
Saving to: ‘image.jpg.11’

image.jpg.11                       6%[==>                                                          ]  42.69K  --.-KB/s   in 0s     

2015-07-01 13:21:43 (500 MB/s) - Read error at byte 43711/700895 (Connection reset by peer). Giving up.

Debugging output from the http server:

I have to send 700895 bytes of content.
I wanted to send 65 bytes of header, and I sent 65.
I sent 700895 bytes of content. I had 0 left to send.

I'd appreciate another set of eyes on this! Why is this happening and how can I fix it?

Upvotes: 0

Views: 1215

Answers (2)

Steffen Ullrich
Steffen Ullrich

Reputation: 123521

My guess is that the error is related to code you have not shown here.

It is a common mistake in simple implementation to not fully read the request but instead only read the first line or some bytes to determine the requested page, then send the response and finally close.

Since at the time of the close there are still unread data from the client, this will result in Connection reset by peer. You don't see this effect with nc because the request you send with nc is probably shorter than the request from the browser and thus all data from the request are read in case of nc, but not in case of browser.

Apart from that your response is invalid even if browsers accept it. Your status line (the first line) stops after the status code instead of adding the reason phrase, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1. Also, you use \n instead of \r\n as line delimiter.

Upvotes: 1

wallyk
wallyk

Reputation: 57784

I don't know if it is necessary, but when I inspect the headers being sent by a simple website, there are quotes around the values:

Accept-Ranges:"bytes"
Cache-Control:"max-age=25920000"
Connection:"Keep-Alive"
Content-Length:"4777"
Content-Type:"image/gif"
Date:"Wed, 01 Jul 2015 17:55:52 GMT"
Expires:"Tue, 26 Apr 2016 17:55:52 GMT"
Keep-Alive:"timeout=30, max=100"
Last-Modified:"Mon, 28 Apr 1997 01:25:47 GMT"
Server:"Apache/1.3.28 (Unix) mod_gzip/1.3.19.1a mod_perl/1.28"

Is it possible the content type is not correct?

Upvotes: 0

Related Questions