0

So I'm writing this simple HTTP Client in C, and, well, I don't know C that well. Here's the gist of it. I got the HTTP client working, I can send the GET request and a get response back. I even can parse the HTTP headers to get the information I want (though my solution to that is admittedly inelegant). The problem is when it's binary information, like a picture file. I'm sure it's something simple, but ... well here's a slimmed down version of what I have.

FILE *fp = fopen("output", "wb"); // Open the file for writing
while (recv(s, buf, MAXDATASIZE - 1, 0) > 0) { //This just iterates over our HTTP response, it works don't worry
    if (is_text == 1) { // Assume I already parsed the headers and know the Content-type
        fprintf(fp, "%s", buf); // This works, it just writes the text to our output file
    }
    else { // Anything not text, this is where the problem is
        fwrite(buf, sizeof buf, 1, fp); // <-- **This is the problem line**
    }
    memset(buf, 0, MAXADATASIZE -1, 0); // Reset the buffer, for the next iteration
}
flose(fp); // Close the file

So, the line I have marked as the problem line does write some binary stuff to my output file, it just never matches the original file. Not only do they differ, they differ in size by like orders of a hundred. It's just not the same file. Yes, I know need to figure out a way to strip the headers or the files will always be different, but clearly that's not even the problem here, yet.

-- Extra information:
    Ubuntu 18.04.5
    gcc version 7.5.0
    "Hardware" is a virtualbox VM, 64-bit

  • 1
    you should check the return value of `fopen` to make sure the file opened correctly. `recv` returns the number of bytes read into `buf`, that's important. `memset` takes 3 arguments, not 4, how does this even compile? (There's no point in `memset`ting `buf` after each iteration anyway, just check the return value of `recv` to see how many bytes were written to it). – yano Sep 07 '20 at 18:15
  • Yeah that's a good question about `memset`, I don't know. Either way, it does compile. I'll add error checking to `fopen` that's a good suggestion, thank you, but it is writing to files, so I don't think that's the problem. And... again I'm not very good at C, but I think I tried to take away that `memset` line as well, because I also though, "who needs it?" but it started messing with my output, so I put it back. – ALittleHelpFromMyFriends Sep 07 '20 at 18:31
  • @yano, to answer your question about `memset`, I just typed it wrong. In my actual code that fourth parameter isn't included. – ALittleHelpFromMyFriends Sep 07 '20 at 18:46

1 Answers1

2

recvreturns the number of bytes read.

ssize_t rb;
FILE *fp = fopen("output", "wb"); // Open the file for writing
while ((rb = recv(s, buf, sizeof(buf), 0)) > 0) { //This just iterates over our HTTP response, it works don't worry
    fwrite(buf, 1, rb, fp); // <-- **This is not the problem line anymore**
}
flose(fp); // Close the file
stderr
  • 143
  • 5
  • Wow! Thank you so much! See, I knew it was something simple. I've marked this as correct, though I can't verify _for sure_ because I still haven't figured out a way to strip the headers before writing to the file. I have another question open for it, but for now the files still differ, though by only about 200 bytes instead of a kilobyte or so, so that feels about the right size for a file with an HTTP header stuffed on top. Thank you so much! – ALittleHelpFromMyFriends Sep 07 '20 at 18:37
  • 1
    `recv` returns -1 on error, which is true. The `while` loop should check for > 0 (don't want to write to file on error and no point writing 0 bytes). – yano Sep 07 '20 at 18:41
  • Confirmed! That was what I needed, thank you so much @stderr I never would have known to change `fwrite()` without you. – ALittleHelpFromMyFriends Sep 07 '20 at 22:28
  • @ALittleHelpFromMyFriends "*I still haven't figured out a way to strip the headers before writing to the file*" - see [my answer](https://stackoverflow.com/a/16247097/65863) to [Differ between header and content of http server response (sockets)](https://stackoverflow.com/questions/16243118/) – Remy Lebeau Sep 08 '20 at 17:12