0

I want to save everything received with GET request to file with this command:

./client http://example.com/1.jpg > image.jpg

My recv_buf is 2000 bytes.

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

send_len = strlen(send_buf); //length of request to send
bytes_send = send(sockfd, send_buf, send_len, 0);

if (bytes_send <= 0)
{
    perror("nothing sended\n");
    exit(1);
}

printf("Bytes send: %d\nSended message: %s\n", bytes_send, send_buf);

// receive data

do {
    bytes_recv = recv(sockfd, recv_buf, sizeof(recv_buf), 0);

    if (bytes_recv <= 0) 
    {
        perror("connection closed or error");
        close(sockfd);
        freeaddrinfo(results);
        exit(0);
    }

    printf("Bytes received: %d\n", bytes_recv);

    //write(1, recv_buf, bytes_recv);

} while (bytes_recv > 0);

I am so far that I can receive data till the end, but I don't know how to combine all the "packages" to one buffer in correct order and then save it to file as binary data (image).

Output is:

./client https://example.com/1.jpg
Bytes received: 2000
Bytes received: 1792
Bytes received: 2000
Bytes received: 1792
Bytes received: 639
connection closed or error: Success
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MUST_DIE
  • 49
  • 1
  • 11
  • fopen() the file, after the recv() success, fwrite() bytes_recv bytes from the recv_buf, fclose() when the recv() loop exits because 0 bytes received. It's that simple. – Martin James Nov 08 '17 at 16:56
  • 1
    where `write(1, recv_buf, bytes_recv);` is commented, using `fwrite(recv_buf, bytes_recv,1,fhandle)` should do the trick (open fhandle in binary mode) – Jean-François Fabre Nov 08 '17 at 16:56
  • Ok thx it worked but how can I save this binary data to single array?Because I want then separate the header and body content and save it to image.jpg? – MUST_DIE Nov 08 '17 at 17:13
  • You don't want to use an array - you want to dynamically allocate memory to store the response and expand it as you receive more of it – Chris Turner Nov 08 '17 at 17:26
  • Ok then lets say, I know the size of the body content and I've allocated enough memory then how can store all the response there (all this packages in correct order)? – MUST_DIE Nov 08 '17 at 17:32
  • Parsing an HTTP header would be another question, and I would be amazed if there are no duplicates. – Martin James Nov 08 '17 at 20:43
  • @Dmitry: you are going about this all wrong. You don't need to save the entire response to a single array at all. Your code is not even implementing the HTTP protocol correctly to begin with. Start by fixing that. Then you would be able to receive just the HTTP headers, and then parse the headers to know how to read the remaining body data so you can write it to file (or to stdout, in the case of your `> image.jpg` example). Related: https://stackoverflow.com/a/7234357/65863 – Remy Lebeau Nov 08 '17 at 20:43

1 Answers1

0

You can use realloc and memcpy as follows:

unsigned char* buf = 0;
int bufsize = 0;
do {
    bytes_recv = recv(sockfd, recv_buf, sizeof(recv_buf), 0);
    if (bytes_recv <= 0) 
    {
        perror("connection closed or error");
        close(sockfd);
        freeaddrinfo(results);
        exit(0);
    }

    buf = realloc(buf, bufsize + bytes_recv);
    memcpy(buf + bufsize, recv_buf, bytes_recv);
    bufsize += bytes_recv;

} while (bytes_recv > 0);

buf will not contain bufsize bytes which has been read. Or write to the file and use malloc and read that file again.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77