08-1 : Domain Name System
도메인 이름 : IP 주소에 부여되는 별칭(가상의 주소)
DNS(Domain Name System) : IP주소와 도메인 이름 사이에서의 변환을 수행하는 시스템
DNS 서버 : 도메인 이름을 IP 주소로 변환
- 모든 컴퓨터에는 디폴트 DNS 서버의 주소가 등록되어있음
- 브라우저 주소창에 도메인 이름 입력시 해당 도메인 이름의 IP주소를 디폴트 DNS 서버를 통해 얻게됨
ping
명령어로 도메인 이름에 해당하는 IP 주소를 얻을 수 있음nslookup
명령어로 디폴트 DNS 서버의 주소를 얻을 수 있음- 호스트가 문의한 도메인 이름의 IP 주소를 디폴트 DNS 서버가 모를 경우 해당 요청에 대해 한단계 상위 계층에 있는 DNS 서버에 질의함
- 최상위 Rood DNS 서버까지 전달된 질의는 하위 DNS 서버에 전달되어 IP주소를 얻어내고, 질의를 시작한 호수트에게 전달됨
08-2 : IP주소와 도메인 이름 사이의 변환
IP주소는 도메인 이름에 비해 상대적으로 변경의 확률이 높음
따라서 프로그램상에서 IP주소보다 도메인 이름을 사용하는 것이 유리하며, 따라서 IP주소와 도메인 이름 사이의 변환함수가 필요함
#include <netdb.h>
struct hostent *gethostbyname(const char *hostname);
// 성공시 hostent 구조체 변수의 주소값, 실패시 NULL 포인터 반환
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
}
h_name
: 공식 도메인 이름(Official domain name)이 저장됨h_aliases
: 공식 도메인 이름 이외에 해당 페이지에 접속할 수 있는 다른 도메인 이름들의 정보(하나의 IP에 여러개의 도메인 이름을 지정할 수 있음)h_addrtype
:h_addr_list
로 반환된 IP주소의 주소체계에 대한 정보h_length
: 함수호출의 결과로 반환된 IP주소의 크기정보 - IPv4는 4, IPv6는 16이 저장됨h_addr_list
: 도메인 이름에 대한 IP주소가 정수의 형태로 반환됨
gethostbyname()
함수를 활용한 예제
// gethostbyname.cpp
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
using namespace std;
void error_handling(char *message);
int main(int argc, char *argv[])
{
struct hostent *host;
if (argc != 2)
{
cout << "Usage : " << argv[0] << " <addr>\n";
exit(1);
}
host = gethostbyname(argv[1]);
if (!host)
error_handling("gethost... error");
cout << "Official name : " << host->h_name << endl;
for (int i = 0; host->h_aliases[i]; i++)
cout << "Aliases " << i + 1 << " : " << host->h_aliases[i] << endl;
cout << "Address type : " << (host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6") << endl;
for (int i = 0; host->h_addr_list[i]; i++)
cout << "IP addr " << i + 1 << " : " << inet_ntoa(*(struct in_addr*)host->h_addr_list[i]) << endl;
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
IP주소를 이용해 도메인 정보를 얻는 함수도 존재
#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family);
// 성공시 hostent 구조체 변수 주소값, 실패시 NULL 포인터 반환
gethostbyaddr()
함수를 활용한 예제
// gethostbyaddr.cpp
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
using namespace std;
void error_handling(char *message);
int main(int argc, char *argv[])
{
struct hostent *host;
struct sockaddr_in addr;
if (argc != 2)
{
cout << "Usage : " << argv[0] << " <IP>\n";
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);
if (!host)
error_handling("gethost... error");
cout << "Official name : " << host->h_name << endl;
for (int i = 0; host->h_aliases[i]; i++)
cout << "Aliases " << i + 1 << " : " << host->h_aliases[i] << endl;
cout << "Address type : " << (host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6") << endl;
for (int i = 0; host->h_addr_list[i]; i++)
cout << "IP addr " << i + 1 << " : " << inet_ntoa(*(struct in_addr*)host->h_addr_list[i]) << endl;
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
08-3 : 윈도우 기반으로 구현하기
윈도우에도 gethostbyname()
함수와 gethostbyaddr()
함수가 존재
#include <winsock2.h>
struct hostent *gethostbyname(const char *name);
// 성공시 hostent 구조체 변수의 주소값, 실패시 NULL 포인터 반환
struct hostent *gethostbyaddr(const char *addr, int len, int type);
// 성공시 hostent 구조체 변수의 주소값, 실패시 NULL 포인터 반환
윈도우 기반 gethostbyname()
함수를 활용한 예제
// gethostbyname_win.cpp
#include <iostream>
#include <winsock2.h>
using namespace std;
void ErrorHandling(char* message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
struct hostent *host;
if (argc != 2)
{
cout << "Usage : " << argv[0] << " <addr>\n";
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error");
host = gethostbyname(argv[1]);
if (!host)
ErrorHandling("gethost... error");
cout << "Official name : " << host->h_name << endl;
for (int i = 0; host->h_aliases[i]; i++)
cout << "Aliases " << i + 1 << " : " << host->h_aliases[i] << endl;
cout << "Address type : " << (host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6") << endl;
for (int i = 0; host->h_addr_list[i]; i++)
cout << "IP addr " << i + 1 << " : " << inet_ntoa(*(struct in_addr*)host->h_addr_list[i]) << endl;
WSACleanup();
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
윈도우 기반 gethostbyaddr()
함수를 활용한 예제
// gethostbyaddr_win.cpp
#include <iostream>
#include <winsock2.h>
using namespace std;
void ErrorHandling(char* message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
struct hostent *host;
SOCKADDR_IN addr;
if (argc != 2)
{
cout << "Usage : " << argv[0] << " <IP>\n";
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error");
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)
ErrorHandling("gethost... error");
cout << "Official name : " << host->h_name << endl;
for (int i = 0; host->h_aliases[i]; i++)
cout << "Aliases " << i + 1 << " : " << host->h_aliases[i] << endl;
cout << "Address type : " << (host->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6") << endl;
for (int i = 0; host->h_addr_list[i]; i++)
cout << "IP addr " << i + 1 << " : " << inet_ntoa(*(struct in_addr*)host->h_addr_list[i]) << endl;
WSACleanup();
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
내용 확인문제
- 다음 중 DNS(Domain Name System)에 대한 설명으로 잘못된 것을 모두 고르면?
- DNS가 존재하기 때문에 IP를 대신해서 도메인 이름을 사용할 수 있다. (O)
- DNS 서버는 사실 라우터를 의미한다. 라우터가 도메인 이름정보를 참조하여 데이터의 진로를 결정하기 때문이다. (X)
- 하나의 DNS 서버에 모든 도메인 정보가 다 등록되어있지는 않다. 그러나 등록되지 않은 도메인의 IP 주소도 얻어올 수 있다. (O)
- DNS 서버는 운영체제에 따라서 구분이 된다. 즉, 윈도우 운영체제용 DNS 서버와 리눅스용 DNS 서버는 구분이 된다. (X)
- 아래의 대화를 읽고, 동수가 제안한 해결책으로 문제가 해결될 수 있는지 말해보자.
정수 : 동수냐? 야! 우리학교 네트워크 망에 연결되어있는 디폴트 DNS 서버가 다운되어서 이력서를 넣어야 할 회사들의홈페이지에 접속이 안돼! 뭔가 방법이 없을까?
동수 : 인터넷과 연결은 되어있는데 DNS 서버만 다운된거야?
정수 : 응! 해결책 뭐 없을까? 그냥 주변에 있는 PC방으로 달려가야하나?
동수 : 그렇게까지 할 필요가 뭐있냐? 내가 우리학교 DNS 서버 IP 주소를 불러줄테니까, 네가 사용하는 컴퓨터의 디폴트 DNS 서버 주소를 변경해!
정수 : 그런다고 되냐? 디폴트 DNS 서버는 반드시 로컬 네트워크상에 연결되어 있어야한다고!
동수 : 아냐! 지난번에 우리학교도 디폴트 DNS 서버가 죽으니까, 네트워크 관리자가 다른 DNS 서버의 IP 주소를 알려주던데?
정수 : 그건 너네 학교에 DNS 서버가 여러대 있으니까 가능했던거야!
동수 : 그런가? 네 말이 맞는 것 같기도 하다. 그럼 얼른 PC방으로 달려가봐라!
가능 - 로컬 네트워크로 연결된 DNS 서버를 반드시 디폴트로 지정해야 하는 것은 아님
- 웹 브라우저의 주소창에 www.orentec.co.kr를 입력해서 메인 페이지가 보이기까지의 과정을 정리해보자. 단, 웹 브라우저가 접속한 디폴트 DNS 서버에는 www.orentec.co.kr에 대한 IP주소가 등록되어 있지 않다고 가정하자.
디폴트 DNS 서버에서 www.orentec.co.kr에 대한 IP주소 탐색 - 디폴트 DNS 서버에 정보가 없으므로 상위 DNS 서버에서 탐색 - 정보가 있을때까지 상위 DNS로 이동, 찾았을시 다시 디폴트 DNS 서버로 전달 - 호스트에 전달
'개인공부 > 윤성우의 열혈 TCP&IP 소켓 프로그래밍' 카테고리의 다른 글
Chapter 10 - 멀티프로세스 기반의 서버구현 (0) | 2023.02.24 |
---|---|
Chapter 09 - 소켓의 다양한 옵션 (0) | 2023.02.24 |
Chapter 07 - 소켓의 우아한 연결종료 (0) | 2023.02.24 |
Chapter 06 - UDP 기반 서버 / 클라이언트 (0) | 2023.02.24 |
Chapter 05 - TCP 기반 서버 / 클라이언트 2 (0) | 2023.02.24 |
댓글