과목명 : 컴퓨터 통신(Computer communication)
수업일자 : 2022년 10월 03일 (월)
1. 도메인 이름 시스템과 이름 변환 함수
1-1. 도메인 이름(Domain name)
- 도메인 이름은 넓은 의미로는 네트워크 상에서 컴퓨터를 식별하는 호스트명을 말하며 좁은 의미로는 도메인 레지스트리에 등록된 이름을 의미합니다.
- IP 주소처럼 호스트나 라우터의 고유한 식별자로 사용합니다.
- IP 주소보다 기억하거나 사용하기 쉽다는 특징을 가집니다.
1-2. 도메인 이름 <-> IP 주소 변환 함수
- IP 주소 -> 도메인 이름으로 변환하는 함수의 경우 대부분의 도메인에서 지원하지 않습니다.
- gethostbyname(), gethostbyaddr() 함수는 모두 hostent 구조체형 포인터를 리턴합니다.
/* 도메인 이름 -> IP 주소 (네트워크 바이트 정렬) */
struct hostent *gethostbyname (
const char *name // 도메인 이름
);
/* IP 주소 -> 도메인 이름(대부분 도메인에서 해당 기능은 지원하지 않음) */
struct hostent *gethostbyaddr (
const char *addr, // IP 주소(네트워크 바이트 정렬)
int len, // IP 주소의 길이
int type // IP 주소의 체계(AF_INET 또는 AF_INET6)
)
1-3. hostent의 구조체
typedef struct hostent {
char* h_name; // official name of host
char** h_aliases; // alias list
short h_addrtype; // host address type
short h_length; // length of address
char** h_addr_list; // list of addresses
#define h_addr h_addr_list[0] // address, for backward compatibility
}HOSTENT;
(1) char* h_name;
- 호스트의 공식 도메인 이름을 나타냅니다.
(2) char** h_aliases;
- 한 호스트가 공식 도메인 이름 외에 다른 이름을 여러 가지 가질 수 있는데 이를 별명(alias name)이라고 합니다. 호스트가 여러 별명을 보유한 경우 이 포인터를 따라가면 모든 별명을 얻을 수 있습니다.
(3) short h_addrtype;
- 주소 체계를 나타내는 값이며 AF_INET 또는 AF_INET6 값이 저장됩니다.
(4) short h_length;
- IP 주소의 길이(바이트 단위)이며 4(IPv4) 또는 16(IPv6)이 저장됩니다.
(5) char** h_addr h_addr list;
- 네트워크 바이트 정렬된 IP 주소이며 한 호스트가 여러 개의 IP 주소를 가진 경우 이 포인터를 따라가면 모든 IP 주소를 얻을 수 있습니다. 특정 호스트에 접속할 때는 대개 첫 번째 IP 주소만 사용하므로 h_addr_list[0]에 접근합니다.
1-4. gethostbyname(), getbyhostaddr() 사용자 정의 함수 정의
- gethostbyname(), getbyhostaddr() 함수를 이용해 도메인 이름과 IPv4 주소를 상호 변환하는 사용자 정의 함수를 작성하면 다음과 같습니다.
// 도메인 이름 -> IPv4 주소
BOOL GetIPAddr(char *name, IN_ADDR *addr)
{
HOSTENT *ptr = gethostbyname(name);
if(ptr == NULL){
err_display("gethostbyname()");
return FALSE;
}
if(ptr->h_addrtype != AF_INET)
return FALSE;
memcpy(addr, ptr->h_addr, ptr->h_length);
return TRUE;
}
// IPv4 주소 -> 도메인 이름
BOOL GetDomainName(IN_ADDR addr, char *name, int namelen)
{
HOSTENT *ptr = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
if(ptr == NULL){
err_display("gethostbyaddr()");
return FALSE;
}
if(ptr->h_addrtype != AF_INET)
return FALSE;
strncpy(name, ptr->h_name, namelen);
return TRUE;
}
(1) 도메인 이름 -> IP 주소 변환
- getbyhostname() 함수를 호출해 HOSTENT 구조체형 포인터를 얻습니다.
- 이후 오류 발생 시, 오류를 출력하고 FALSE를 리턴합니다.
- AF_INET 주소 체계가 아닐 시 FALSE를 리턴합니다.
- 위의 두 조건문을 만족하지 않는다면 IP 주소를 복사한 후 TRUE를 리턴합니다.
(2) IP 주소 -> 도메인 이름
- getbyhostaddr() 함수를 호출해 HOSTENT 구조체형 포인터를 얻습니다.
- 이후 오류 발생 시, 오류를 출력하고 FALSE를 리턴합니다.
- AF_INET 주소 체계가 아닐 시 FALSE를 리턴합니다.
- 위의 두 조건문을 만족하지 않는다면 도메인 이름을 복사한 후 TRUE를 리턴합니다.
1-5. 도메인 이름 변환 함수 실습
#pragma comment(lib, "ws2_32")
#include <winsock2.h>
#include <stdio.h>
// 소켓 함수 오류 출력
void err_display(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf("[%s] %s", msg, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
}
// 도메인 이름 -> IPv4 주소
BOOL GetIPAddr(char *name, IN_ADDR *addr)
{
HOSTENT *ptr = gethostbyname(name);
if(ptr == NULL){
err_display("gethostbyname()");
return FALSE;
}
if(ptr->h_addrtype != AF_INET)
return FALSE;
memcpy(addr, ptr->h_addr, ptr->h_length);
return TRUE;
}
// IPv4 주소 -> 도메인 이름
BOOL GetDomainName(IN_ADDR addr, char *name, int namelen)
{
HOSTENT *ptr = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
if(ptr == NULL){
err_display("gethostbyaddr()");
return FALSE;
}
if(ptr->h_addrtype != AF_INET)
return FALSE;
strncpy(name, ptr->h_name, namelen);
return TRUE;
}
int main(int argc, char *argv[])
{
WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return 1;
#ifndef DEBUG
char TESTNAME[100];
printf("Domain Name : ");
gets_s(TESTNAME);
#endif
printf("도메인 이름(변환 전) = %s\n", TESTNAME);
// 도메인 이름 -> IP 주소
IN_ADDR addr;
if(GetIPAddr(TESTNAME, &addr)){
// 성공이면 결과 출력
printf("IP 주소(변환 후) = %s\n", inet_ntoa(addr));
// IP 주소 -> 도메인 이름
char name[256];
if(GetDomainName(addr, name, sizeof(name))){
// 성공이면 결과 출력
printf("도메인 이름(다시 변환 후) = %s\n", name);
}
}
WSACleanup();
return 0;
}
<실행 결과>
- 위와 같이 도메인명이 IP 주소로 변환되고 다시 한 번 도메인명이 IP 주소로 변환된 것을 알 수 있습니다.
- 위에서 언급된 것처럼, 도메인명 -> IP 주소 변환은 허용하나, IP 주소 -> 도메인명의 변환을 허용하지 않는 곳도 존재합니다.
2. DNS 서비스의 클라이언트 프로그램이 동작하는 원리
- 앞에서 도메인 이름에 대해 잠시 언급이 있었지만 더 자세히 알아보도록 하겠습니다.
2-1. DNS(Domain Name Service)의 정의
- 보통 엔드 포인트에 있는 유저들은 웹 브라우저의 주소창에 주소를 입력하고 실제 웹 사이트에 접속을 합니다. www.naver.com 이라는 서버는 IP 주소 체계로 통신하지만 사람의 편의를 위해 기억하기 쉬운 www.naver.com와 같은 도메인 이름을 사용하게 되고 사람이 입력한 도메인 주소를 수로 이루어진 주소 체계인 IP 주소로 변환하는 과정이 필요한데 이를 담당하는 시스템이 바로 DNS(Domain name service)입니다.
2-2. 구성 요소
(1) Domain name space
- 최상위에 루트 DNS 서버가 존재하고 하위로 내려갈수록 인터넷에 연결된 모든 노드들이 보여지는 연속적인 계층 구조
(2) Name server
- 도메인명을 IP 주소로 변환시키기 위해 Domain name space의 구조에 대한 정보를 필요로 하며 이 정보를 보유하고 있는 서버 도메인 이름을 IP 주소로 변환시키는 것을 Name service라고 합니다.
(3) 리졸버(Resolver)
- DNS 클라이언트의 요청을 Name server로 전달하고, Name server로부터 도메인 이름과 IP 주소를 받아 클라이언트 측으로 전달하는 기능을 수행하는 주체를 의미합니다.
2-3. 동작 원리
- 일반적으로 많이 사용되는 웹 사이트인 네이버 기준 동작 예시입니다.
(1) 클라이언트에서 웹 브라우저를 열고 www.naver.com 라는 도메인명을 입력하고 접속을 시도합니다.
(2) Local DNS에 DNS Query를 하기 전에 캐시 파일의 정보에 IP 주소가 존재하는지 확인합니다. 매 번 DNS 서버에 질의하지 않고 캐시에 저장된 주소값을 빠르게 알아내기 위함입니다.
(3) 만약 캐시에 존재하지 않을 시, 이때 클라이언트에서 Local DNS 측으로 해당 도메인명에 대한 IP 주소를 요청하는 Query를 보냅니다.
(4) Local DNS는 해당 도메인명에 대한 IP 주소를 알아내기 위해 다른 DNS 서버들과 통신을 시작하게 되는데 우선적으로 만약 여러 서버들과 통신했음에도 불구하고 주소를 알아내기 어렵다면 루트 DNS 서버에게 해당 도메인명에 대한 IP 주소를 요청합니다.
(5) 루트 DNS 서버는 해당 도메인명의 IP 주소를 모르므로 Local DNS server에 해당 도메인명의 TLD인 ".com"을 관리하는 TLD 네임 서버 정보를 보냅니다.
(6) Local DNS는 ".com"을 관리하는 TLD 네임 서버에게 해당 도메인명의 IP 주소를 요청하는 Query를 보냅니다.
(7) TLD 네임 서버에도 해당 도메인의 IP 주소가 존재하지 않을 경우 해당 도메인을 관리하는 네임 서버 정보를 응답합니다.
(8) 해당 도메인을 관리하는 DNS 서버에는 도메인에 대한 IP 주소가 존재하므로 Local DNS 서버에게 해당 도메인의 IP 주소 값을 응답해 줍니다.
(9) IP 주소를 수신한 Local DNS는 캐싱 파일에 해당 정보를 저장하여 이후 동일한 도메인명으로 IP 주소를 요청했을 때 DNS 서버에 쿼리를 보내지 않고 캐시에 저장된 값을 통해 빠른 응답을 제공하게 됩니다.
- 학부에서 수강했던 전공 수업 내용을 정리하는 포스팅입니다.
- 내용 중에서 오타 또는 잘못된 내용이 있을 시 지적해 주시기 바랍니다.
'전공 수업 > 컴퓨터 통신(Computer Communication)' 카테고리의 다른 글
[8주 차] - TCP 서버 - 클라이언트의 동작, 여러 가지 함수 (0) | 2022.10.17 |
---|---|
[7주 차] - TCP 서버 - 클라이언트의 동작, 여러 가지 함수 (0) | 2022.10.11 |
[5주 차] - Windows 소켓 주소 구조체 (1) (2) | 2022.09.27 |
[4주 차] - Windows 소켓 시작하기 (0) | 2022.09.19 |
[3주 차] - Windows 소켓, 간단한 서버 소켓 프로그램 작성 (0) | 2022.09.12 |
댓글