1

I am writing a web server in C. I am able to send my html code in the response body but I tried an JPG image but I get "http://localhost:port/image.jpg" cannot be displayed because it contains errors.

this is a snippet from my webserver code:

this is my response header:

char * responseheader= "HTTP/1.1 200 OK\r\n "Content-Type: image/jpg\r\n" "Content-Length: 110000\r\n\r\n";

//read the file imagefile and store it in the buffer and append it to response header.

for (i=0;(i<(sizeof(buffer))&&((ch=fgetc(imagefile))!=EOF)&&(ch!='\n')); i++) { printf("%c", ch) buffer[i] = ch; } strcat(responseheader, buffer);

if (strncmp(requestbuff, "GET /image.jpg", 15) { printf("server: loading image...\n"); send(socketfd, responseheader, sizeof(responseheader), 0); }

output:

on my webrowser firefox, I type localhost:port/index.html and the page loads fine. once my server reads the request GET /image.jpg..., I send the buffer above. Now, when my page loads, the image doesn't show up but as a small error box and when I right click on it and view image, it states the error above.

I'm not really sure how I can append the image with my response header. I tried sending the file directly to the web browser once I used open() after sending the response; same story. One thing I do know is that the image is "binary data", full of characters that I can see when I use notepad.

I've looked for hours, browsing the university library, and looking for books, but I haven't seen any implementation in HTTP/C to properly display an image.

Inside my index.html I used <img src=/image.jpg></img> which triggers the browser request to my web server.

Also, is there a book that any of you would recommend concerning HTTP and C web servers that covers this material? Thanks.

Note: I understand this may be easier to implement in PHP/JAVA/JAVASCRIPT; I can only write this in C at the moment

Best Regards.

2
  • 1) You have an additional Content-type: text/html, remove that. 2) Does the image really have exactly 110000 bytes? 3) Do not use strcat(), it stops at the first zero byte, use memcpy(). 4) You need a reasonable sized buffer for the memcpy(), which you have to allocate somehow (static or dyamic) Commented Dec 1, 2018 at 11:20
  • thanks for the response; that was a typo with the "content-type: text/html"; and the file image is 108642 according to ls-l Commented Dec 1, 2018 at 11:24

1 Answer 1

1

There are multiple issues. firstly, you have a duplicate Content-Type header that is invalid (Forward-slash versus backslash, and also you're not sending HTML). Remove that first off.

Secondly, a binary file (such as a JPEG image) may (and often does) contain '00' bytes, which strcat will consider as string terminators.

Thirdly, you are invoking strcat to append to a pointer that may (as per the C standard) be stored in read-only memory (as it is a string literal).

Finally, sizeof(responseheader) is simply 4 or 8 (whatever the size of a pointer is on your system). You are conflating the behavior of sizeof on an array with its behavior on a pointer. You really mean strlen(responseheader) in the send() call.

In order to fix this all, I would use two send() calls (since HTTP uses TCP, they will be seen as a single stream of bytes). Do not modify responseheader, and simply send the header in the first call. Then, send the payload from the buffer in a second call, send(socketfd, buffer, i, 0); (after your for loop, i, will contain the number of bytes stored in buffer).

EDIT: also, you need to set Content-Length properly (to the size of your file of your file). Because of this change your response header creation to the following, with the snprintf() call AFTER your for loop to read the file:

char responseheader[80];

snprintf(responseheader, sizeof(responseheader),
    "HTTP/1.1 200 OK\r\n" 
    "Content-Type: image/jpg\r\n"
    "Content-Length: %d\r\n\r\n", i
    );
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.