1

All I get are some characters (4) everytime I want to get an image. I want to save an image with this command ./client example.com/image.jpg > img.jpg I think there is smth wrong with the recv at the end.

    sprintf(request, "%s %s %s%s%s%s", "GET", path, "HTTP/1.1\r\n", 
                                        "HOST:", hostname, "\r\n\r\n");

    //Send some data with TCP
    if(send(sockfd, request, strlen(request), 0) < 0) {
        printf("Send failed\n");
        exit(1);
    }


   // printf("Request sended\n");

    if(recv(sockfd, server_reply , sizeof(server_reply), 0) < 0) {//receive answer
        printf("recv failed\n");
    }

    char *data = strstr(server_reply, "\r\n\r\n");//save data after header
    data+=4;

    //printf("Server reply: \n");//print the answer
    puts(data);

    close(sockfd);

    return 0;
}

I think that I can't receive all image binary data but I don't know how to get everything correctly.

MUST_DIE
  • 49
  • 1
  • 11
  • Lots of things can be wrong, but if your `recv` call is not returning as much data as you expect, you need to run it inside a loop until you get all the data. Moreover, do not expect `recv` to return a `'\0'` terminated string. An image, in particular, is binary data, so `puts` would be a bad way to try to print it out in any case. – jxh Nov 02 '17 at 00:47
  • 1
    Related: https://stackoverflow.com/questions/32856200/receive-recv-data-until-end-of-stream-using-http – jxh Nov 02 '17 at 00:54
  • @jxh is correct... the link he referenced correctly tells you that the Response Headers will tell you how to read the content-body of the response. Additionally, if you DO receive an "image", you won't be able to use "puts()" to output it, since "puts() is for outputting a "a string", not binary data. – TonyB Nov 02 '17 at 01:15

1 Answers1

0

There are several things wrong with your code:

  • You expect a single send to send all data.
    But send might only send part of the data and you have to check the return value to see how much data were sent and if necessary call send again.
  • You expect a single recv to return the full response.
    But recv will only return as much data it can get at once and only up to the given size. If there are more than only a few data the chance is high that you need multiple recv to get all data. How much each recv will return can also differ between exchanging data on localhost and LAN.
  • You expect the TCP connection to get immediately closed when the response is done.
    But since you are using HTTP/1.1 (and not HTTP/1.0) and don't specify an explicit Connection: close the server might keep the connection open to wait for more requests. This means your last recv might hang.
  • You expect the image to be in one piece after the HTTP header.
    But since you use HTTP/1.1 and not HTTP/1.0 you have to deal with chunked responses too, i.e. the body delivered in pieces where each piece is prefixed with the size.

Thus, I recommend to study what send and recv actually do. Also, by looking only at some traces of HTTP traffic or simply examples you don't get the complexity of the actual standard. If you want to keep it simple use HTTP/1.0 not HTTP/1.1.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172