팥빵 먹으면서 코딩하는 블로그

06-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 도메인 이름과 인터넷 주소 본문

study/NETWORK PROGRAMMING

06-2. [Linux/Ubuntu] 네트워크 프로그래밍 - 도메인 이름과 인터넷 주소

김팥빵_ 2025. 4. 11. 16:27

도메인 이름(Domain Name)과 DNS 서버

  • 도메인 이름
    • "영문"으로 표현되는 계층적 주소 체계 방식
    • Human-readable address
      • IP주소를 대신해서 사용하는 서버의 주소 : www.google.com
      • 도메인 이름IP 주소로 변환이 된 이후, 서버에 접속이 가능함 -> 도메인이 있음에도 접속하려면 IP가 필수적으로 필요하므로.
    • 각 나라마다 존재하는 Network Information Center에서 관리
      • 한국은 KRNIC 담당
  • Domain Name System(DNS)
    • IP주소와 / 도메인 이름 사이에서 / 변환을 수행하는 시스템
    • 경북대 DNS 서버: 155.230.10.2
  • DNS 서버
    • 도메인 이름을 IP 주소로 변환해주는 서버
      • www.google.com > 해당 IP 주소로 변환
    • DNS는 일종의 분산 데이터베이스 시스템 -> DNS는 하나만 있지 않음.
  • DNS와 IP 주소
    • 호스트는 Default DNS Server에게 도메인 이름의 IP 주소를 요청
    • 해당 도메인 이름에 대한 IP 주소가 없으면
      • default DNS Server는 상위 계층의 DNS Server에 요청
      • Root DNS Server에게 요청
  • 도메인 이름을 이용한 특정 서버 접속 과정
    • 도메인 이름을 이용하여 특정 서버에 접속
    • DNS 서버에 해당 도메인의 IP주소를 요청함
    • DNS 서버의 응답으로 받은 IP주소를 이용하여 특정 서버에 접속

서버 접속과정

인터넷상에서의 주소 체계

 

DNS Server

  • DNS 서버 역할
  • ping & nslookup
    • ping 명령어
      • ICMP 프로토콜을 사용한다. 
      • 도메인 이름에 해당하는 IP주소를 확인하고 싶을 때 사용
      • ex.) ping www.google.com -> ip주소까지 딸려서 출력됨.
      • iputils 설치해야 할거임.
    • nslookup 명령어
      • DNS 서버에 도메인 이름을 입력하면 해당 IP주소를 반환
      • nslookup 설치
        • $ sudo apt install dnsutils
  • 여기서 ping & nslookup은 단순 명령어에 불과함.
  • 실제로 이 명령어를 구현할 수 있는 함수가 있음 (다음

 

도메인 이름을 이용한 IP주소 얻어오기 - gethostbyname()

  • gethostbyname() 함수
    • 문자열 형태의 도메인 이름으로 IP주소 정보를 얻음
#include <netdb.h>

struct hostent*	gethostbyname(const char *hostname);
-> 성공 시 hostent 구조체 변수의 주소 값, 실패 시 NULL 포인터 반환
  • hostname: 문자열 도메인 이름 전달

 

  • 도메인 이름을 사용하는 이유
    1. IP주소는 도메인 이름에 비해 / 변동이 심함 (도메인 이름은 회사 이름과 일맥상통하므로 함부로 바꾸지 않음.)
    2. 프로그램 코드에서 서버의 IP 주소를 직접 입력하는 경우,
      • 서버의 IP주소가 변경될 때마다 컴파일을 다시 해야 됨
    3. 상대적으로 변동이 덜한 도메인 이름 사용
      • 서버에 대한 IP주소를 얻어오게 구현하면, 코드 재컴파일이 필요 없음
  • hostent 구조체
struct hostent
{
	char *h_name;				//	official	name
	char **h_aliases;			//	alias	list
	int h_addrtype;				//	Host	address	type
	int h_length;				//	address	length
	char **h_addr_list;			//	address	list
}
  • 구조체 hostent에 채워지는 정보의 형태
    • h_name : 공식 도메인 이름
    • h_aliases : 별칭의 도메인 이름
    • h_addrtype : 반환된 IP 주소의 정보가 IPv4인 경우, AF_INET이 반환
    • h_length : 반환된 IP 정보의 크기 저장 (IPv4 : 4, IPv6 : 16)
    • h_addr_list : IP 주소 정보, 둘 이상인 경우, 모두 반환
      • 접속자 수가 맣은 서버는 하나의도메인에 여러 IP 주소 사용
  • gethostbyname() 함수 호출 예
host = gethostbyname(argv[1]);
if(!host)
    error_handling("gethost ... error");
    
printf("Official name: %s\n", host->h_name);

for(i=0; host->h_aliases[i]; i++)	// host->h_aliases[i]가 null이 아닐때까지 받아옴.
    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++) // host->h_addr_list[i]가 null이 아닐때까지 반복
	printf("IP addr %d: %s\n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
    // h_addr_list를 char* inet_ntoa() 함수를 이용해서 변환함
    // inet_ntoa()함수로 우리가 읽을 수 있는 ip형태로 바꿔서 출력

 

도메인 이름을 이용한 IP주소 얻어오기 - gethostbyaddr()

  • gethostbyaddr() 함수
    • IP주소를 이용하여 도메인 정보를 얻어옴: gethostbyname() 함수의 역 기능
#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
    • AF_INET: IPv4
    • AF_INET6: IPv6

 

  • gethostbyaddr 함수 호출의 예
memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr=inet_addr(argv[1]);

host = gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);

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]));
  • struct sockaddr_in addr;    // addr-> 일반 구조체 변수
  • gethosybyaddr((char*)&addr.sin_addr, 4, AF_INET)    // &addr.sin_addr -> 구조체 변수의 주소
  • 주소를 받아주면 된다 -> 따라서 malloc 쓸 일은 없음