이번 주제는 인터넷에서의 IP 주소를 구하는 방법에 대한 얘기입니다. 챙피하게도 아직까지 네트워크 함수를 이용하여 내부 로컬 IP를 구하는 방법을 모릅니다. 그래서 popen() 함수를 사용해서 시스템 명령을 직접 캡쳐했습니다. 즉, ifconfig를 실행하고 결과를 읽어들여 로컬 네트워크에서의 IP를 구하는 것이죠. 조금 둔한 방법이고 마음에 들지는 않지만 제일 확실한 벙법이더군요.
이번에는 인턴넷에서의 IP를 구하는 방법이 궁금해 졌습니다. 웹 검색을 의존했습니다만, 가장 정확히 아는 방법은 인터넷 IP를 알려 주는 사이트를 이용하는 것입니다. 아래의 사이트는 방문하는 것 만으로도 인터넷에서 할당된 IP를 구할 수 있습니다.
웹페이지를 직접 읽는 방법
그런데 문제는 웹브라우저에서는 쉬운데, 일반 C 언어에서 웹 소스를 어떻게 읽어 들여야할지 모르겠더군요. 80포트로 connect 하기만 하면 되는 줄 알았는데, HTTP 프로토콜에 맞추어 전문을 만들어서 전송해 주어야 웹 소스를 수신 받을 수 있었습니다. 웹 소스를 구하는 요청 전문 구성은 아래와 같습니다.
GET / HTTP/1.1 {cr lf}
User-Agent: Mozilla/4.0 {cr lf}
content-type:text/html {cr lf}
Connection: close {cr lf}
프로그랭을 작성하지 않아도 털넷을 이용하여 웹 소스를 구할 수 있습니다. 아래의 캡쳐에서 흰색은 타이핑한 부분이고 노랑색은 웹서버로부터 수신한 내용입니다.
]$ telnet checkip.dyndns.org 80 Trying 204.13.249.70... Connected to checkip.dyndns.org (204.13.249.70). Escape character is '^]'. GET / HTTP/1.1 User-Agent: Mozilla/4.0 content-type:text/html Connection: close HTTP/1.1 200 OK Content-Type: text/html Server: DynDNS-CheckIP/1.0 Connection: close Cache-Control: no-cache Pragma: no-cache Content-Length: 106 <html><head><title>Current IP Check</title></head><body>Current IP Address: 211.239.155.97</body></html> Connection closed by foreign host. ~]$
이렇게 80포트를 이용하면 웹 페이지를 읽어 들일 수 있습니다. 이 방법을 이용하는 C 코드를 작성했습니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #define BUFF_SIZE 1024 int main( int argc, char **argv) { int hsocket; struct sockaddr_in server_addr; struct hostent *host_entry; char *p_enter= "\r\n"; char *p_get= "GET / HTTP/1.1\r\n User-Agent: Mozilla/4.0\r\n content-type:text/html\r\n \ Connection: close\r\n\r\n"; char buff[BUFF_SIZE+1]; host_entry = gethostbyname( "checkip.dyndns.org"); if ( !host_entry) { printf( "gethostbyname() 실행 실패/n"); exit( 1); } hsocket = socket( PF_INET, SOCK_STREAM, 0); if( -1 == hsocket) { printf( "socket 생성 실패\n"); exit( 1); } memset( &server_addr, 0, sizeof( server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons( 80); memcpy((void *)(&server_addr.sin_addr), (void *)(host_entry->h_addr), sizeof(server_addr.sin_addr)); if( -1 == connect( hsocket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) ) { printf( "접속 실패n"); } else { memset( buff, '\0', BUFF_SIZE+1); send( hsocket, p_get, strlen( p_get)+1, 0); if ( 0 == read( hsocket, buff, BUFF_SIZE)) { printf( "웹 소스 구하기 실패\n"); } else { printf( "%s\n", buff); } close( hsocket); } return 0; }
위의 소스를 컴파일하고 실행하면 http://checkip.dyndns.org의 기본 페이지의 소스가 출력됩니다.
]$ ./a.out HTTP/1.1 200 OK Content-Type: text/html Server: DynDNS-CheckIP/1.0 Connection: close Cache-Control: no-cache Pragma: no-cache Content-Length: 106 <html><head><title>Current IP Check</title></head><body>Current IP Address: 211.239.155.97</body></html> ]$
수신한 소스에서 IP를 구하면 되겠습니다.