책/윤성우 TCPIP

chapter 08 -2 , ip주소와 도메인 이름 사이의 변환 (3)

babystep 2020. 12. 9. 23:58
728x90
  • 구조체 hostent 정의부분만 놓고 보면 구조체멤버 h_addr_list 가리키는 것은 문자열 포인터 배열( 이상의 문자열 주소 값으로 구성된 배열)이다. 그러나 문자열 포인터 배열이 실제 가리키는 것은(실제 저장하고 있는 것은)문자열의 주소값이 아닌 in_addr 구조체 변수의 주소 값이다.
  •  

 

 

  • 그림은 구조체 멤버 h_addr_list 참조관계를 보이고 있다. 때문에 예제에서 형변환 inet_ntoa함수의 호출을 동반하는 것이다.
  • in_addr* 아닌  char*인가?
    • 구조체 hostent 멤버 h_addr_list 가리키는 배열이 구조체 in_addr 포인터 배열이 아닌, char 포인터 배열인 이유가 궁금할 것이다. 왜냐하면 hostent IPv4만을 위해 정의된 구조체가 아니기때문에 h_addr_list 가리키는 배열에는 IPv6기반의 주소 정보가 저장될 수도 있다. 때문에 일반화를 위해서 char 포인터 배열로 선언한 것이다.  "void 포인터 배열로 선언했으면 의미가 조금 통했겠는데요" 라고 생각할수도 있다. 맞는말이지만 지금 공부하는 소켓과련 함수들은 void 포인터가 표준화되기 이전에 정의되어 당시에는 참조의 대상이 일정하지 않은 경우 char* 포인터 변수를 활용하였다.

 

  • IP주소를 이용해서 도메인 정보 얻어오기
    • gethostbyaddr 함수는 IP주소를 이용해서 도메인 정보를 얻을 호출하는 함수이다.
      • #include <netdb.h>
      • struct hostent * gethostbyaddr( const char * addr, socklen_t len, int family);
        • -> 성공시 hostent 구조체 변수의 주소값 실패시 NULL 포인터 반환
      • addr : IP 주소를 지니는 in_addr 구조체 변수의 포인터 전달, IPv4이외의 다양한 정보를 전달 있도록 일반화하기 위해서 매개변수를 char 포인터로 선언
      • len  :  번째 인자로 전달된 주소정보의길이, IPv4 경우 4, Ipv6 경우 16 전달
      • family : 주소체계 정보 전달.IPv4 경우 AF_INET , Ipv6 경우 AF_INET6전달
    • gethostbyaddr.c 예제

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <netdb.h>

void error_handling(const char* message);

 

int main(int argc, char *argv[])

{

    int i;

    struct hostent *host;

    struct sockaddr_in addr;

    if(argc != 2){

        printf("Usage :%s <IP>\n",argv[0]);

        exit(1);

    }

 

    memset(&addr, 0, sizeof(addr));

    addr.sin_addr.s_addr = inet_addr(argv[1]);

    host = gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET); // 이부분만 제외하면

    //  gethostbyname.c 예제와 크게 다르지 않다.

 

    if( !host )

        error_handling("gethost... error");

 

    printf("Official name : %s \n", host->h_name);

 

    for(i =0; host->h_aliases[i]; i++)

        printf("Aliases %d : %s \n", i + 1, host->h_aliases[i]);

 

    printf("Address type: %s \n",

        (host->h_addrtype == AF_INET)?"AF_INET":"AF_INET6");

 

    for(i = 0; host->h_addr_list[i]; i++)

        printf("IP addr %d: %s \n", i+1,

            inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));

 

    return 0;

}

 

void error_handling(const char* message)

{

    fputs(message, stderr);

    fputc('\n', stderr);

    exit(1);

}

 

 

 

- 실행결과 

728x90