gethostbyname和endianness - 如何返回字节?

时间:2015-05-14 08:31:08

标签: winapi language-agnostic winsock endianness

在我的(英特尔)x86机器上,我注意到,如果我printf gethostbyname localhost的结果,我会得到100007F,即使MSDN documentation状态它应该以网络字节顺序返回IP,即大端。我搜索了一下,发现了this topic。基于那里的答案,我推断出无论字节顺序如何,字节序列都是相同的,因此,对于localhost,我在内存中同时使用Intel和AMD芯片:

7F|00|00|01

因此,读取带有英特尔芯片的内存会导致“反转”。结果,在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;
}

输出:

enter image description here


注意:我有一个朋友在他的AMD CPU上运行它,令人惊讶的是,显然它也是100007F对他来说。我先前的假设是错的,还是我的朋友喝醉了?

2 个答案:

答案 0 :(得分:1)

hostent结构中包含的地址按网络字节顺序排列。

如果您的代码有其他建议,那么您会错误解释该代码并得出错误的结论。

在网络字节顺序中,在小端主机上,127.0.0.10x0100007f。要了解其工作原理,请记住在小端主机上,首先存储最低有效字节。那是0x7f。因此,字节在内存中以此顺序显示,0x7f0x000x000x01。因此,它代表127.0.0.1

现在,大端主机上的那些相同字节将代表不同的32位值。在大端主机上,第一个字节是最重要的,因此0x7f0x000x000x01将代表值0x7f000001。< / p>

答案 1 :(得分:0)

AMD芯片是小端,就像英特尔芯片一样。没有区别。

如果你想看到big-endian结果,你需要在大端系统上运行,例如以big-endian模式运行的ARM或MIPS芯片,或SPARC,或PPC,或68K或ALPHA或者现在很少见的许多旧的大端架构中的任何一种(ARM和MIPS都是混合端芯片,可以配置为以big-endian或little-endian模式运行,尽管它们通常以big-endian模式运行)。