- 구조체 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);
}
- 실행결과
'책 > 윤성우 TCPIP' 카테고리의 다른 글
09-1 소켓의 옵션과 입출력 버퍼의 크기 (2) (0) | 2020.12.11 |
---|---|
09-1 소켓의 옵션과 입출력 버퍼의 크기 (0) | 2020.12.10 |
< 08-2 : IP 주소와 도메인 이름 사이의 변환 예제 > (0) | 2020.12.08 |
Chapter 08 도메인 이름과 인터넷 주소 (0) | 2020.12.07 |
07 -1 TCP 기반의 Half-close (0) | 2020.12.06 |