인터넷 주소 변환 School of Electronics and Information. Kyung Hee University. Dae Sun Kim <dskim@networking.khu.ac.kr>
네트워크 프로그래밍 네트워크 프로그래밍 이란? 네트워크로 연결되어 있는 두 호스트간의 데이터 송수신. 파일 입출력과의 차이점은 데이터를 주고 받는 대상에 있다 socket socket File Write Write Read Read
Server socket vs Client socket IP 주소 할당.(bind) 연결 요청 대기 상태 (listen) 4. 연결 수락!(accept) 소켓 생성(socket) 연결요청.(connect)
File Descriptor Program 1 2 3 4 5 6 Operating System 표준입력 표준출력 표준에러 표준입력 1 표준출력 2 표준에러 3 파일 A 4 소켓 B 5 소켓 C 6 파일 D
소켓 생성 및 타입 소켓의 생성 int socket (int domain, int type, int protocol) 연결지향형 소켓, 비연결지향형 소켓 CASE Domain Type Protocol 1 PF_INET SOCK_STREAM IPPROTO_TCP(0) 2 SOCK_DGRAM IPPROTO_UDP(0)
IPv4 주소 구조체 IPv4 주소체계를 나타내는 구조체 struct sockaddr_in { sa_family_t sin_family; /* 주소 체계(AF_INET) */ uint16_t sin_port; /* port 정보 */ struct in_addr sin_addr; /* 32 비트 IP 주소정보 */ char sin_zero[8]; /* 사용되지 않음 */ }; struct in_addr { uint32_t s_addr; /* 32비트 IP 주소정보 */ };
네트워크 바이트 네트워크 바이트 순서 Big Endian: Network Byte Order Little Endian: Host Byte Order unsigned short htons(unsigned short); unsigned short ntohs(unsigned short); unsigend long htonl(unsigned long); unsigned long ntohl(unsigned long); ‘h’ : host byte order ‘n’ : network byte order ‘s’ : short (16 bit) ‘l’ : long (32 bit)
FROM Dotted-Decimal Notation TO Big-Endian 32 비 트 정수형 데이터 (Network byte order) FROM Big-Endian 32 비트 정수형 데이터 (Network byte order) TO Dotted-Decimal Notation unsigned long inet_addr(const char * string) char * inet_ntoa(struct in_addr addr)
인터넷 주소 초기화 Template 1: struct sockaddr_in addr; 2: char *serv_ip="211.217.168.13"; 3: char *serv_port="9190"; 4: memset(&addr, 0, sizeof(addr_len)); 5: addr.sin_family = AF_INET; 6: addr.sin_addr.s_addr = inet_addr(serv_ip); 7: addr.sin_port = htons(atoi(serv_port));
인터넷 주소 초기화 Template 1: struct sockaddr_in addr; 2: char *serv_port="9190"; 3: memset(&addr, 0, sizeof(addr_len)); 4: addr.sin_family = AF_INET; 5: addr.sin_addr.s_addr = htonl(INADDR_ANY); 6: addr.sin_port = htons(atoi(serv_port));
소켓에 주소 할당하기
주소 정보 할당 #include <sys/type.h> #include <sys/socket.h> int bind(int sockfd, struct sockaddr * myaddr, int addrlen); sockfd : 주소를 할당하고자 하는 소켓의 파일 디스크 립터를 인자로 전달 myaddr : 할당하고자 하는 주소 정보를 지니고 있는 sockaddr_in 구조체 변수의 포인터를 인자로 전달 addrlen : 인자로 전달될 주소 정보 구조체의 길이를 전달
socket 함수와 bind 함수는 특정 프로토콜 체계를 위한 함수가 아님 프로토콜 체계에 따라 주소 체계가 다름 socket 함수와 bind 함수는 특정 프로토콜 체계를 위한 함수가 아님 프로토콜에 독립적 따라서, 일반적(범용적으로 사용가능하게끔) 선언되어야 함 Local Unix 프로토콜을 위한 sockaddr_un 구조체의 포인터도 인자값으로 사 용할 수 있어야 함 struct sockaddr { sa_family sin_family; char sa_data[14]; };
프로그램 예제 프로그램 명: bind_sock.c serv_sock=socket(PF_INET, SOCK_STREAM, 0); /* 소켓 생성 */ if(serv_sock == -1) error_handling("socket() error"); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr(serv_ip); //htons(INADDR_ANY); serv_addr.sin_port=htons(atoi(serv_port)); if( bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1 ) /* 소켓에 주소를 할당 */ error_handling("bind() error");
Port 번호 확인 함수 getservbyname()은 well-known 포트를 사용하는 TCP/IP 응용 프로그램의 포트번호를 알아내는 함수 서비스 이름과 프로토콜을 인자로 하여 호출하면 서비스 관련 각종 정보를 포함하고 있는 servent라는 구조체의 포인터를 반환 #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> struct servent * getservbyname (string service, string protocol)
Port 번호 확인 함수 struct servent { char *s_name; /* 서비스 이름 */ char **s_aliases; /* 별명 목록 */ int s_port; /* 포트번호 */ char *s_proto; /* 사용하는 프로토콜 */ };
프로그램 예제 프로그램 명: byte_order.c int main(void) { struct servent *servent; servent = getservbyname("telnet", "tcp"); //echo ,udp if( servent == NULL ) { printf( "서비스 정보를 얻을 수 없음. \n\n"); exit(0); } printf("UDP 에코 포트번호(네트워크 순서) : %d \n", servent->s_port); printf("UDP 에코 포트번호(호스트 순서) : %d \n", ntohs(servent->s_port)); return 0;
IP 주소 변환 함수 gethostbyname() inet_addr() inet_pton() inet_ntoa() www.khu.ac.kr 10100011 10110100 01100000 01000111 163.180.96.71 도메인 네임 IP 주소(binary) 10진 표기법 gethostbyname() inet_addr() inet_pton() inet_ntoa() Inet_ntop() gethostbyaddr()
프로그램 예제 프로그램 명: ascii_ip.c 15 int main(int argc, char *argv[]) { 16 struct in_addr inaddr; // 32비트 IP 주소 구조체 17 char buf[20]; 18 19 if(argc < 2) { 20 printf("사용법 : %s IP 주소(dotted decimal) \n", argv[0]); 21 exit(0); 22 } 23 printf("* 입력한 dotted decimal IP 주소: %s\n", argv[1]); 24 25 inet_pton(AF_INET, argv[1], &inaddr.s_addr); 26 printf(" inet_pton(%s) = 0x%X\n", argv[1], inaddr.s_addr); 27 inet_ntop(AF_INET, &inaddr.s_addr, buf, sizeof(buf)); 28 printf(" inet_ntop(0x%X) = %s\n", inaddr.s_addr,buf); 29 30 return 0;}
도메인 주소 변환 #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> struct hostent *gethostbyname(const char *hname) 도메인 네임으로부터 IP 주소를 얻는 함수 struct hostent *gethostbyaddr(const char *in_addr, int len, int family) IP 주소로부터 도메인 네임을 얻는 함수
struct hostent { char *h_name; /* 호스트 이름 */ char **h_aliases; /* 호스트 별명들 */ int h_addrtype; /* 호스트 주소의 종류 */ int h_length; /* 주소의 크기 */ char **h_addr_list; /* IP 주소 리스트 */ }; #define h_addr haddr_list[0]; /* 첫 번째(대표) 주소 */
프로그램 예제 프로그램 명: get_hostent.c hp = gethostbyname(argv[1]); if(hp==NULL) { printf("gethostbyname fail\n"); exit(0); } printf("호스트 이름 : %s\n", hp->h_name); printf("호스트 주소타입 번호: %d\n", hp->h_addrtype); printf("호스트 주소의 길이 : %d 바이트\n", hp->h_length); for( i=0; hp->h_addr_list[i]; i++) { memcpy(&in.s_addr, hp->h_addr_list[i],sizeof(in.s_addr)); inet_ntop(AF_INET, &in, buf, sizeof(buf)); printf("IP 주소(%d 번째) : %s\n",i+1,buf); for( i=0; hp->h_aliases[i]; i++) printf("호스트 별명(%d 번째) : %s ",i+1, hp->h_aliases[i]); puts("");
프로그램 예제 프로그램 명: get_host_byaddr.c int main(int argc, char *argv[]) { struct hostent *myhost; struct in_addr in; if(argc < 2) { printf("사용법 : %s ip_address \n", argv[0]); exit(0); } inet_pton(AF_INET, argv[1], &in.s_addr);// dotted decimal->32bit 주소 myhost = gethostbyaddr((char *)&(in.s_addr),sizeof(in.s_addr), AF_INET); if (myhost == NULL) { printf("Error at gethostbyaddr() \n"); printf("호스트 이름 : %s\n", myhost->h_name); return 0;
실습과제 실습서버 (163.180.116.241) well-known port를 검사 하여 열려 있는 포트 번호를 출력 하시오. 파일명: port_scan.c