简体   繁体   中英

Byte ordering HTTP Client

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?

It wouldn't make a whole lot of sense to write out the image's bytes before deciding which order they should be in. What would be your next line be, fopen() ?


If you're doing something architecture dependent like this, it's best to guard the case-specific sections with #if / #elif , and use #else to emit #error with a diagnostic message. If everything is supposed to still work, it can just be #warning ... but do put the warning in. For later, when it stops working.

Configuration macros you can test should include #ifdef __BIG_ENDIAN__ and #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ; you can see what else is available by 'compiling' with -E -dD . [there will be a lot; grep is your friend]

Oh, and "big endian" means if you're reading bytes in address order (a[0], a[1], a[2], ...), then the byte at this end is the most significant/highest 'digit'. Hence "big-endian".

edit: this may also be of concern...

FILE *sockfile = fdopen(sockfd, "r+");                     // "r+"
if (sockfile == NULL)
    ERROR_EXIT("fdopen: %s\n", strerror(errno));

if (fputs("GET / HTTP/1.1\r\n\r\n", sockfile) == EOF)      // fputs...

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".

Look here , here and here for examples.

'Hope that helps...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM