주소 변환
-
프로그램이 사용자에게 입력받는 주소는
Dotted-Decimal
형태의 문자열인 IP 주소 또는 호스트 이름일 것이다. 따라서 주소를 변환해주어야 한다. -
사용자가 입력한 IP 주소 문자열을
uint32_t
형태로 변환시켜주는 작업이 반드시 필요하다. -
경우에 따라서는
IP
주소를 다시 문자열 형태로 변환시키는 작업도 필요할 수 있다.
아래는 주소를 변환할 수 있는 API 이다.
함수 | 설명 |
---|---|
int inet_addr(const char *cp) |
cp 문자열 IP 주소를 네트워크 바이트 순서 in_addr_t 로 반환 |
int inet_network(const char *cp) |
cp 문자열 IP 주소를 호스트 바이트 순서 in_addr_t 로 반환 |
int inet_aton(const char *cp, strcut in_addr *inp) |
cp 문자열 IP 네트워크 바이트 순서 inp 로 변환 |
char *inet_ntoa(struct in_addr in); |
네트워크 바이트 순서로 된 in_addr 구조체 주소에서 IP 주소 문자열 반환 |
int inet_pton(int af, const char *src, void *dst); |
af 인자로 3계층 프로토콜 선택 가능, src 문자열 주소를 dst 로 변환 |
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); |
af 인자로 3계층 프로토콜을 선택 가능, src 주소 구조체를 문자열 주소로 변환 |
IP 주소를 정수로 변환하여 출력하는 예제
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
int main(int argc, char** argv) {
uint32_t ip_int;
char *ip_str = "127.0.0.1";
ip_int = inet_network(ip_str);
printf("string: %s, decimal: %u, hex: %x\n",
ip_str, ip_int, ip_int);
ip_int = htonl(ip_int);
printf("after htonl - decimal: %u, hex: %x \n",
ip_int, ip_int);
return 0;
}
-
inet_network
함수를 이용하여 문자열로 된IP
주소를uint32_t
타입 변수에 호스트 바이트 순서로 저장한다. -
htonl
함수를 이용하여 호스트 바이트 순서로 되어 있는 주소를 네트워크 바이트 순서로 변경한다.
주소 변환 함수 예제
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int print_addr(struct sockaddr_in *);
int main(char argc, char* argv[]) {
char *sample_ip = "127.0.0.1";
int port = 9002;
struct sockaddr_in sock_addr1, sock_addr2, sock_addr3;
sock_addr1.sin_family = AF_INET;
sock_addr1.sin_addr.s_addr = inet_addr(sample_ip);
sock_addr1.sin_port = htons(port);
sock_addr2.sin_family = AF_INET;
inet_aton(sample_ip, &(sock_addr2.sin_addr));
sock_addr2.sin_port = htons(port);
sock_addr2.sin_family = AF_INET;
inet_aton(sample_ip, &(sock_addr2.sin_addr));
sock_addr2.sin_port = htons(port);
sock_addr3.sin_family = AF_INET;
inet_pton(AF_INET, sample_ip, &(sock_addr3.sin_addr));
sock_addr3.sin_port = htons(port);
print_addr(&sock_addr1);
print_addr(&sock_addr2);
print_addr(&sock_addr3);
printf("===== ntoa =====\n");
printf("IP: %s \n", inet_ntoa(sock_addr1.sin_addr));
printf("IP: %s \n", inet_ntoa(sock_addr2.sin_addr));
printf("IP: %s \n", inet_ntoa(sock_addr3.sin_addr));
return 0;
}
int print_addr(struct sockaddr_in *address) {
int port;
char txt[INET_ADDRSTRLEN];
port = ntohs(address->sin_port);
inet_ntop(AF_INET, &(((struct sockaddr_in *) address) -> sin_addr), txt, sizeof(struct sockaddr_in));
printf("ip: %s, port: %d \n", txt, address->sin_port);
return 0;
}
호스트 이름과 IP 주소
-
실제로 우리가 작성하는 프로그램은
IP
주소 문자열보다 호스트 이름을 인자로 받을 확률이 높다. -
호스트 이름 문자열을
IP
주소로 변환하는 과정은 단순 변환이 아니다. 네임 서버에 해당 내용을 조회하고 그 결과값을 알려주는 과정이 포함된다.
#include <netdb.h>
#include <sys/socket.h>
struct hosten *gethostbyname(const char *name);
- 호스트 이름을 네임서버에 조회하여 성공하면 네임 서버는 여러 가지 정보를 제공한다. 이 정보를 저장하기 위해서는
hostent
라는 구조체가 사용된다.
struct hostent {
char *h_name; // 호스트의 공식 이름
char **h_aliases; // 가명 리스트 (마지막 인자는 NULL)
int h_addrtype; // 호스트 주소 타입 (IPv4, IPv6)
int h_length; // 주소의 길이
char **h_addr_list; // 주소 리스트 (마지막 인자는 NULL)
}
#define h_addr h_addr_list[0]; // 주소 중 첫 번째 엔트리
- 여러가지 정보 중에 우리가 관심 있는 것은 IP 주소이다. IP 주소는
gethostbyname
하뭇의 실행 결과 얻을 수 있는hostent
구조체의 멤버 변수 중에서 주소 리스트인h_addr_list
를 통해서 얻어올 수 있다.
호스트 이름으로 IP
주소를 조회하는 예제
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
void err_proc(const char *);
int main(int argc, char *argv[]) {
struct hostent *ent;
struct in_addr **res;
int i = 0;
if (argc != 2) {
fprintf(stderr, "usage: %s <hostname> \n", argv[0]);
return -1;
}
ent = gethostbyname(argv[1]);
if (ent == NULL) err_proc("gethostbyname");
res = (struct in_addr **) ent->h_addr_list;
printf("hostname: %s \n", ent->h_name);
while(res[i] != NULL) {
printf("%s", inet_ntoa(*res[i]));
i++;
}
printf("\n");
}
void err_proc(const char *str) {
fprintf(stderr, "%s: %s\n", str, strerror(errno));
exit(errno);
}
-
예제 프로그램은 프로그램 실행시에 호스트 이름을 입력 인자로 받는다.
-
프로그램 실행 시 입력받은 호스트 이름 문자열을 이용하여
gethostbyname
함수를 실행한다.
참고 문헌
>> Home