I wrote a simple HTTP Client that can request data from a host.
I am using getaddrinfo(3). With "GET / HTTP/1.1" request I am able to download HTML page of a given http Host.
Here is a part of my code:
struct addrinfo hints, *ai;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // Internet Protocol (IP) socket
hints.ai_socktype = SOCK_STREAM; // TCP
int res = getaddrinfo("example.com", "http", &hints, &ai);
if (res != 0)
ERROR_EXIT("getaddrinfo: %s\n", gai_strerror(res));
int sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd < 0)
ERROR_EXIT("socket: %s\n", strerror(errno));
if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)
ERROR_EXIT("connect: %s\n", strerror(errno));
FILE *sockfile = fdopen(sockfd, "r+");
if (sockfile == NULL)
ERROR_EXIT("fdopen: %s\n", strerror(errno));
// send a GET request to the server:
if (fputs("GET / HTTP/1.1\r\n\r\n", sockfile) == EOF)
ERROR_EXIT("fputs: %s\n", strerror(errno));
if (fflush(sockfile) == EOF)
ERROR_EXIT("fflush: %s\n", strerror(errno));
char buf[1024];
// print the reply:
while (fgets(buf, sizeof(buf), sockfile) != NULL)
fputs(buf, stdout);
fclose(sockfile);
return 0;
Downloading a HTML page works ok, but downloading PNG image for example "GET /image.png HTTP/1.1\r\n\r\n"
gives something like this:
???????ݹh??DHDZ?yW]%?9a??J?6F?Ѧ?E???ݐTd?US?:)??I??M,?-????=??U??&???Nr? ???б???
b??]??8?6+?;??i䂢d?G?WA?rԺ?H[??]?Z5????g?{8??i\?qAC?@c??v.?rb??'<?T?????O?z?
q,yĜ?ŷZI???X??fM?l?Z??l:;M???ۦ?????c?\\?W6+???o?}_???紈A??GvG?p??6{??{%?????0?{?
%??ژ??l?$r<?????ft*'W?N?m߂Ҿ4??E?:^?#?&?%%
????Dw??Z?$??1?4?l%&2?f-5!?? ?E? 8...
I understand that this is a byte transfer and that I have to do byte ordering, but don't know where to begin.
I know that I need to use ntohl(3) and Big-endian order for PNG images. Can Someone give me directions what to look up and how to approach this?
Do I save this output to .png file and then do byte order or do I do before I create a .png file?
The problem is more complex than just "byte order".
The Good News is that byte order is probably irrelevant. The code you've got now should work just fine sending and receiving text strings with the server.
The Bad News is that you need to connect differently if you want to read binary data from the server. Several considerations:
It sounds like you probably don't need to worry about "POST", "PUT" ... or anything but "GET".
It also sounds like you don't need to worry about "MIME Types" or "uuencoding/decoding" - you'll just be reading the data as-is.
You should definitely read the Content-Type
and Content-Length
headers from the server's HTTP response.
Perhaps the simplest approach is just call fgetc()
in a loop if you're reading binary data. Use fgets()
for strings, and fgetc()
for Content-Length
bytes to read the image.
You'll probably want to do an fopen()
to write the image bytes to a file.
But calling fgets() eliminates the need to worry about "byte order".