gethostbyname 和 endianness - 如何返回字节?
gethostbyname and endianness - how are the bytes returned?
在我的(英特尔)x86 机器上,我注意到如果我 printf
gethostbyname
的结果 localhost
,我得到 100007F
,即使MSDN documentation states it should return the IP in network byte order, aka big endian. I searched a bit and found this topic。根据那里的答案,我推断出无论字节顺序如何,字节序列都是相同的,因此,对于 localhost
,我会在 Intel 和 AMD 芯片的内存中都有这个:
7F|00|00|01
因此,读取 带有 Intel 芯片的内存会产生 'reversed' 结果,而在 AMD CPU 上,我会得到 0x7F000001。这个假设正确吗?这似乎是唯一可能的解释,但我想确定一下。
这是我正在使用的代码:
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char **argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData;
int iResult;
DWORD dwError;
int i = 0;
struct hostent *remoteHost;
char *host_name;
struct in_addr addr;
char **pAlias;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
host_name = "localhost";
// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if (isalpha(host_name[0])) { /* host address is a name */
printf("Calling gethostbyname with %s\n", host_name);
remoteHost = gethostbyname(host_name);
}
else {
printf("Calling gethostbyaddr with %s\n", host_name);
addr.s_addr = inet_addr(host_name);
if (addr.s_addr == INADDR_NONE) {
printf("The IPv4 address entered must be a legal address\n");
return 1;
}
else
remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (remoteHost == NULL) {
dwError = WSAGetLastError();
if (dwError != 0) {
if (dwError == WSAHOST_NOT_FOUND) {
printf("Host not found\n");
return 1;
}
else if (dwError == WSANO_DATA) {
printf("No data record found\n");
return 1;
}
else {
printf("Function failed with error: %ld\n", dwError);
return 1;
}
}
}
else {
printf("Function returned:\n");
printf("\tOfficial name: %s\n", remoteHost->h_name);
for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
}
printf("\tAddress type: ");
switch (remoteHost->h_addrtype) {
case AF_INET:
printf("AF_INET\n");
break;
case AF_INET6:
printf("AF_INET6\n");
break;
case AF_NETBIOS:
printf("AF_NETBIOS\n");
break;
default:
printf(" %d\n", remoteHost->h_addrtype);
break;
}
printf("\tAddress length: %d\n", remoteHost->h_length);
if (remoteHost->h_addrtype == AF_INET) {
while (remoteHost->h_addr_list[i] != 0) {
addr.s_addr = *(u_long *)remoteHost->h_addr_list[i++];
printf("\tIPv4 Address #%d: %X %s\n", i, addr.s_addr, inet_ntoa(addr));
}
}
else if (remoteHost->h_addrtype == AF_INET6)
printf("\tRemotehost is an IPv6 address\n");
}
getchar();
return 0;
}
输出:
注意:我有一个朋友 运行 在他的 AMD CPU 上使用这个,而且令人惊讶的是,显然这对他来说也是 100007F
。是我之前的假设错了,还是我朋友d运行k?
hostent
结构中包含的地址是按网络字节顺序排列的。
如果您的代码给出了相反的建议,那么您就是在误解该代码并得出错误的结论。
在网络字节顺序中,在小端主机上,127.0.0.1
是 0x0100007f
。要了解这是如何工作的,请记住在小端主机上,首先存储最低有效字节。那是 0x7f
。所以字节在内存中的出现顺序是0x7f
、0x00
、0x00
、0x01
。因此,这代表 127.0.0.1
.
现在,大端主机上的那些相同字节将代表不同的 32 位值。在大端主机上,第一个字节是最重要的,因此 0x7f
、0x00
、0x00
、0x01
将表示值 0x7f000001
。
AMD 芯片与 Intel 芯片一样是小端。没有区别。
如果你想看到大端结果,你需要运行在大端系统上,比如ARM或MIPS芯片运行在大端模式下,或 SPARC,或 PPC,或 68K 或 ALPHA,或许多现在很少见的旧大端架构中的任何一个(ARM 和 MIPS 是混合端芯片,可以在任一大端中配置为 运行或小端模式,尽管它们通常 运行 在大端模式下)。
在我的(英特尔)x86 机器上,我注意到如果我 printf
gethostbyname
的结果 localhost
,我得到 100007F
,即使MSDN documentation states it should return the IP in network byte order, aka big endian. I searched a bit and found this topic。根据那里的答案,我推断出无论字节顺序如何,字节序列都是相同的,因此,对于 localhost
,我会在 Intel 和 AMD 芯片的内存中都有这个:
7F|00|00|01
因此,读取 带有 Intel 芯片的内存会产生 'reversed' 结果,而在 AMD CPU 上,我会得到 0x7F000001。这个假设正确吗?这似乎是唯一可能的解释,但我想确定一下。
这是我正在使用的代码:
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char **argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData;
int iResult;
DWORD dwError;
int i = 0;
struct hostent *remoteHost;
char *host_name;
struct in_addr addr;
char **pAlias;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
host_name = "localhost";
// If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
if (isalpha(host_name[0])) { /* host address is a name */
printf("Calling gethostbyname with %s\n", host_name);
remoteHost = gethostbyname(host_name);
}
else {
printf("Calling gethostbyaddr with %s\n", host_name);
addr.s_addr = inet_addr(host_name);
if (addr.s_addr == INADDR_NONE) {
printf("The IPv4 address entered must be a legal address\n");
return 1;
}
else
remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
}
if (remoteHost == NULL) {
dwError = WSAGetLastError();
if (dwError != 0) {
if (dwError == WSAHOST_NOT_FOUND) {
printf("Host not found\n");
return 1;
}
else if (dwError == WSANO_DATA) {
printf("No data record found\n");
return 1;
}
else {
printf("Function failed with error: %ld\n", dwError);
return 1;
}
}
}
else {
printf("Function returned:\n");
printf("\tOfficial name: %s\n", remoteHost->h_name);
for (pAlias = remoteHost->h_aliases; *pAlias != 0; pAlias++) {
printf("\tAlternate name #%d: %s\n", ++i, *pAlias);
}
printf("\tAddress type: ");
switch (remoteHost->h_addrtype) {
case AF_INET:
printf("AF_INET\n");
break;
case AF_INET6:
printf("AF_INET6\n");
break;
case AF_NETBIOS:
printf("AF_NETBIOS\n");
break;
default:
printf(" %d\n", remoteHost->h_addrtype);
break;
}
printf("\tAddress length: %d\n", remoteHost->h_length);
if (remoteHost->h_addrtype == AF_INET) {
while (remoteHost->h_addr_list[i] != 0) {
addr.s_addr = *(u_long *)remoteHost->h_addr_list[i++];
printf("\tIPv4 Address #%d: %X %s\n", i, addr.s_addr, inet_ntoa(addr));
}
}
else if (remoteHost->h_addrtype == AF_INET6)
printf("\tRemotehost is an IPv6 address\n");
}
getchar();
return 0;
}
输出:
注意:我有一个朋友 运行 在他的 AMD CPU 上使用这个,而且令人惊讶的是,显然这对他来说也是 100007F
。是我之前的假设错了,还是我朋友d运行k?
hostent
结构中包含的地址是按网络字节顺序排列的。
如果您的代码给出了相反的建议,那么您就是在误解该代码并得出错误的结论。
在网络字节顺序中,在小端主机上,127.0.0.1
是 0x0100007f
。要了解这是如何工作的,请记住在小端主机上,首先存储最低有效字节。那是 0x7f
。所以字节在内存中的出现顺序是0x7f
、0x00
、0x00
、0x01
。因此,这代表 127.0.0.1
.
现在,大端主机上的那些相同字节将代表不同的 32 位值。在大端主机上,第一个字节是最重要的,因此 0x7f
、0x00
、0x00
、0x01
将表示值 0x7f000001
。
AMD 芯片与 Intel 芯片一样是小端。没有区别。
如果你想看到大端结果,你需要运行在大端系统上,比如ARM或MIPS芯片运行在大端模式下,或 SPARC,或 PPC,或 68K 或 ALPHA,或许多现在很少见的旧大端架构中的任何一个(ARM 和 MIPS 是混合端芯片,可以在任一大端中配置为 运行或小端模式,尽管它们通常 运行 在大端模式下)。