字节排序 HTTP 客户端
Byte ordering 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 页面工作正常,但下载 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...
我知道这是一个字节传输,我必须进行字节排序,但不知道从哪里开始。
我知道我需要对 PNG 图像使用 ntohl(3) 和 Big-endian 顺序。有人可以告诉我要查找的内容以及如何处理吗?
我是将此输出保存到 .png 文件然后执行字节顺序还是在创建 .png 文件之前执行?
在决定图像的顺序之前写出图像的字节没有多大意义。你的下一行是什么,fopen()
?
如果你正在做像这样依赖于架构的事情,最好用 #if
/#elif
来保护特定案例的部分,然后使用#else
发出 #error
诊断信息。
如果一切 应该 仍然有效,它可以只是 #warning
... 但一定要放入警告。稍后,当它停止工作时。
您可以测试的配置宏应该包括 #ifdef __BIG_ENDIAN__
和 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
;你可以通过 'compiling' 和 -E -dD
查看还有什么可用的。 [会有很多; grep 是你的朋友]
哦,"big endian" 表示如果您按地址顺序读取字节 (a[0], a[1], a[2], ...),那么这一端的字节最多significant/highest'digit'。因此 "big-endian".
编辑:这也可能是一个问题...
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...
问题比 "byte order" 更复杂。
好消息是字节顺序可能无关紧要。您现在获得的代码应该可以很好地与服务器发送和接收文本字符串。
坏消息是,如果您想从服务器读取 二进制 数据,您需要以不同的方式连接。几个注意事项:
听起来您可能不需要担心 "POST"、"PUT" ... 或除 "GET".
以外的任何问题
听起来您也不必担心 "MIME Types" 或 "uuencoding/decoding" - 您只需读取数据 as-is.
您应该绝对从服务器的 HTTP 响应中读取 Content-Type
和 Content-Length
headers。
如果您正在读取二进制数据,也许最简单的方法就是在循环中调用 fgetc()
。对字符串使用 fgets()
,对 Content-Length
字节使用 fgetc()
来读取图像。
您可能想要 fopen()
将图像字节写入文件。
但是调用 fgets() 就不用担心 "byte order".
'希望对您有所帮助...
我编写了一个简单的 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 页面工作正常,但下载 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...
我知道这是一个字节传输,我必须进行字节排序,但不知道从哪里开始。
我知道我需要对 PNG 图像使用 ntohl(3) 和 Big-endian 顺序。有人可以告诉我要查找的内容以及如何处理吗?
我是将此输出保存到 .png 文件然后执行字节顺序还是在创建 .png 文件之前执行?
在决定图像的顺序之前写出图像的字节没有多大意义。你的下一行是什么,fopen()
?
如果你正在做像这样依赖于架构的事情,最好用 #if
/#elif
来保护特定案例的部分,然后使用#else
发出 #error
诊断信息。
如果一切 应该 仍然有效,它可以只是 #warning
... 但一定要放入警告。稍后,当它停止工作时。
您可以测试的配置宏应该包括 #ifdef __BIG_ENDIAN__
和 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
;你可以通过 'compiling' 和 -E -dD
查看还有什么可用的。 [会有很多; grep 是你的朋友]
哦,"big endian" 表示如果您按地址顺序读取字节 (a[0], a[1], a[2], ...),那么这一端的字节最多significant/highest'digit'。因此 "big-endian".
编辑:这也可能是一个问题...
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...
问题比 "byte order" 更复杂。
好消息是字节顺序可能无关紧要。您现在获得的代码应该可以很好地与服务器发送和接收文本字符串。
坏消息是,如果您想从服务器读取 二进制 数据,您需要以不同的方式连接。几个注意事项:
听起来您可能不需要担心 "POST"、"PUT" ... 或除 "GET".
以外的任何问题听起来您也不必担心 "MIME Types" 或 "uuencoding/decoding" - 您只需读取数据 as-is.
您应该绝对从服务器的 HTTP 响应中读取
Content-Type
和Content-Length
headers。如果您正在读取二进制数据,也许最简单的方法就是在循环中调用
fgetc()
。对字符串使用fgets()
,对Content-Length
字节使用fgetc()
来读取图像。您可能想要
fopen()
将图像字节写入文件。但是调用 fgets() 就不用担心 "byte order".
'希望对您有所帮助...