2015-05-14 2 views
0

На моей (Intel) x86 машине, я заметил, что если я printf результаты gethostbyname для localhost, я получаю 100007F, даже несмотря на то, MSDN documentation утверждает, он должен вернуть IP в сетевом порядке байт, так называемый большой обратный порядок байт. Я немного искал и нашел this topic. На основании ответов там, я вывел последовательность байтов не будет таким же, независимо от порядка байтов, поэтому для localhost, я бы это в памяти на обоих Intel и AMD чипы:gethostbyname и endianness - как возвращаются байты?

7F|00|00|01

Таким образом, читает, что память с чипом Intel приводит к «обратному» результату, а на процессоре AMD я получаю 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, и удивительно, видимо, для него тоже 100007F. Является ли мое предыдущее предположение неправильным, или мой друг пьян?

+0

Я не уверен, но вы не должны использовать одну из функций 'ntohx' для преобразования сетевого байтового порядка в порядок байтов хоста, например [' ntohs'] (https://msdn.microsoft. ком/де-де/библиотека/окно/настольное/ms740075% 2 = vs.85% 29.aspx)? – honk

+0

@honk Конечно, я мог бы, но я пытаюсь понять, почему возвращаемое значение (по-видимому) находится в неправильной конъюнктуре. – szczurcio

+0

А, ок. Я действительно не попадал туда, куда вы стреляли.Можете ли вы добавить код к своему вопросу, который показывает, как вы обращались и печатали переменную, о которой говорите? – honk

ответ

1

Адреса, содержащиеся в структуре hostent, находятся в сетевом порядке.

Если у вас есть код, который предполагает иное, вы неверно истолковываете этот код и делаете неверный вывод.

В сетевом порядке порядка, на небольшом концевом хосте, 127.0.0.1 есть 0x0100007f. Чтобы увидеть, как это работает, помните, что на маленьком конечном узле сначала запоминается младший байт. Это 0x7f. Таким образом, байты отображаются в этом порядке в памяти, 0x7f, 0x00, 0x00, 0x01. И это поэтому представляет 127.0.0.1.

Теперь те же байты на хосте большого конца будут представлять собой другое 32-битное значение. В случае с большим эндианским хостом первый байт, если наиболее значимый, и поэтому 0x7f, 0x00, 0x00, 0x01 будет представлять значение 0x7f000001.

+0

Да, это мне очень ясно; так как я использую код MSDN, я думаю, там проблем нет, поэтому я пытаюсь выяснить, где я делаю эту ошибку. – szczurcio

+0

Я попытался объяснить это ..... –

+0

Да, объяснение приятно, спасибо :). Я добавил этот комментарий, прежде чем отредактировать ответ. Еще один вопрос: как указано в оригинальной записи, мой друг запустил это на чипе AMD, который имеет большой размер, но получил тот же результат. Зачем? Разве это не должно быть «0x7F000001», как вы сказали? – szczurcio

0

Микросхемы AMD немного ориентированы, как и чипы Intel. Нет никакой разницы.

Если вы хотите увидеть результат в формате big-endian, вам нужно запустить в системе с большим энтузиазмом, например, как микросхема ARM или MIPS, работающая в режиме большого конца, или SPARC, или PPC, или 68K или ALPHA, или любой из многих старых архитектур с большим энтузиазмом, которые в настоящее время редко встречаются (ARM и MIPS - это смешанные трициальные чипы, которые могут быть сконфигурированы для работы в режиме «большой» или «мало-по-восточному»), хотя обычно они работают в режиме big-endian Режим).

+0

Я не знаю, я был убежден, что AMD - это, в основном, big-endian, непонятно почему. Во всяком случае, поскольку Windows не может работать на big-endian (кроме некоторых неясных версий), это перестает быть проблемой. – szczurcio