简体   繁体   English

字节订购HTTP客户端

[英]Byte ordering HTTP Client

I wrote a simple HTTP Client that can request data from a host. 我写了一个简单的HTTP客户端,可以从主机请求数据。

I am using getaddrinfo(3). 我正在使用getaddrinfo(3)。 With "GET / HTTP/1.1" request I am able to download HTML page of a given http Host. 使用“GET / HTTP / 1.1”请求,我可以下载给定http主机的HTML页面。

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: 下载HTML页面工作正常,但下载PNG图像例如"GET /image.png HTTP/1.1\\r\\n\\r\\n"提供如下内容:

???????ݹ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. 我知道我需要对PNG图像使用ntohl(3)和Big-endian顺序。 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? 我是否将此输出保存到.png文件,然后执行字节顺序或在创建.png文件之前执行此操作?

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() ? 在决定它们应该处于哪个顺序之前写出图像的字节是没有多大意义的。你的下一行是什么, 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 / #elif来保护特定于案例的部分,并使用#else发出带有诊断消息的#error If everything is supposed to still work, it can just be #warning ... but do put the warning in. For later, when it stops working. 如果一切都应该仍然有效,它可以只是#warning ......但是请将警告输入。稍后,当它停止工作时。

Configuration macros you can test should include #ifdef __BIG_ENDIAN__ and #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ; 您可以测试的配置宏应该包括#ifdef __BIG_ENDIAN__#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ; you can see what else is available by 'compiling' with -E -dD . 你可以通过-E -dD '编译'来看看还有什么可用。 [there will be a lot; [会有很多; grep is your friend] grep是你的朋友]

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'. 哦,“big endian”意味着如果你按地址顺序读取字节(a [0],a [1],a [2],...),那么这一端的字节是最重要/最高的'数字'。 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". 听起来你可能不需要担心“POST”,“PUT”......或者除了“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. 听起来你也不必担心“MIME类型”或“uuencoding / decoding” - 你只是按原样阅读数据。

  • You should definitely read the Content-Type and Content-Length headers from the server's HTTP response. 一定要从服务器的HTTP响应中读取Content-TypeContent-Length标头。

  • Perhaps the simplest approach is just call fgetc() in a loop if you're reading binary data. 也许最简单的方法是在循环中调用fgetc() ,如果你正在读取二进制数据。 Use fgets() for strings, and fgetc() for Content-Length bytes to read the image. 对字符串使用fgets() ,对Content-Length字节使用fgetc()来读取图像。

  • You'll probably want to do an fopen() to write the image bytes to a file. 您可能希望使用fopen()将图像字节写入文件。

  • But calling fgets() eliminates the need to worry about "byte order". 但是调用fgets()消除了担心“字节顺序”的需要。

Look here , here and here for examples. 这里这里这里的例子。

'Hope that helps... '希望有帮助......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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