字节排序HTTP客户端

时间:2019-04-10 17:54:53

标签: c http client

我写了一个简单的HTTP客户端,可以从主机请求数据。

我正在使用getaddrinfo(3)。通过“ GET / HTTP / 1.1”请求,我可以下载给定http主机的HTML页面。

这是我的代码的一部分:

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;

下载HTML页面可以正常工作,但是下载"GET /image.png HTTP/1.1\r\n\r\n"这样的PNG图片可以得到以下效果:

???????ݹ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...

我知道这是一个字节传输,我必须进行字节排序,但是不知道从哪里开始。

我知道我需要对PNG图像使用ntohl(3)和Big-endian顺序。有人可以指导我查找什么内容以及如何进行处理吗?

我是否将此输出保存到.png文件,然后按字节顺序处理?还是在创建.png文件之前执行该操作?

2 个答案:

答案 0 :(得分:0)

在决定图像的字节顺序之前写出图像的字节并没有多大意义。fopen()的下一行是什么?


如果您要执行类似这样的体系结构,最好使用#if / #elif 保护特定于案例的部分,并使用#else发出带有诊断消息的#error。 如果一切应该仍能正常工作,则可以只是#warning ...,但是要发出警告。稍后,当它停止工作时。

您可以测试的配置宏应包含#ifdef __BIG_ENDIAN__#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;您可以通过-E -dD进行“编译”来查看其他可用内容。 [会有很多; grep是你的朋友]

哦,“大端”表示如果您按地址顺序(a [0],a [1],a [2],...)读取字节,则此字节为最高有效/最高“数字”。因此是“大端”。

编辑:这可能也值得关注...

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

答案 1 :(得分:0)

这个问题比“字节顺序”还要复杂。

好消息是字节顺序可能与无关。您现在获得的代码应该可以在服务器上很好地发送和接收文本字符串。

坏消息是,如果要从服务器读取 binary 数据,则需要不同地连接 。一些注意事项:

  • 听起来您可能不需要担心“ POST”,“ PUT” ...或“ GET”以外的任何内容。

  • 听起来您也不必担心“ MIME类型”或“ uuencoding /解码”,您只需按原样读取数据即可。

  • 您应该确定从服务器的HTTP响应中读取Content-TypeContent-Length标头。

  • 如果要读取二进制数据,也许最简单的方法就是在循环中调用fgetc()。将fgets()用于字符串,将fgetc()用于Content-Length字节以读取图像。

  • 您可能需要执行fopen()来将图像字节写入文件。

  • 但是调用fgets()无需担心“字节顺序”。

hereherehere为例。

'希望有帮助...