티스토리 뷰
1. getaddrinfo() 함수
호스트와 서비스명에 해당하는 IP 주소와 포트로 찾아 변환한다.
기존 gethostbyname()과 getserverbyname() 함수를 대체하였다.
#include <netdb.h>
int getaddrinfo(const char *host, const char *service,
const struct addrinfo *hints, struct addrinfo **result);
성공하면 '0'을 리턴하고, 에러가 발생하면 '0'이 아닌 값을 리턴
getaddrinfo()함수는 host, service, hist 값을 입력으로 result로부터 정보를 추출하는 구조이다.
addrinfo 구조체는 아래와 같다.
int ai_flags; /* 입력 플래그 (AI_* 상수) */
int ai_family; /* 주소 패밀리 : AF_INET, AF_INET6 */
int ai_socktype; /* 종류 : SOCK_STREAM, SOCK_DGRAM */
int ai_protocol; /* 소켓 프로토콜 */
size_t ai_addrlen; /* ai_addr 이 가르키는 구조체 크기 */
char * ai_canonname; /* 공식 호스트 명 */
struct sockaddr *ai_addr; /* 소켓 주소 구조체를 가르키는 포인터 */
struct addrinfo *ai_next; /* 링크드 리스트에서 다음 구조체 */
};
1.1. hints 인자에 대한 고찰
hints 인자를 통해서 getaddrinfo() 함수에서 리턴하는 주소 구조체의 정보를 선택적으로 취할 수 있다.
ai_flags, ai_family, ai_socktype, ai_protocol만 설정할 수 있다.
ai_family에는 AF_INET, AF_INET6, AF_UNSPEC 설정 가능. 마지막 값은 모든 종류를 리턴하도록 강제한다.
ai_socktype에는 SOCK_DGRAM, SOCK_STREAM, 0이 가능, 0이면 모든 값을 리턴
ai_protocol에는 대충 '0'을 설정한다.
ai_flags는 getaddrinfo()함수의 수행 방식을 변경하는 비트 마스크다. '0'혹은 아래 값과 OR연산한다.
flags | 설명 |
AI_ADDRCONFIG | 로컬 시스템에 IPv4, IPv6 중에 하나가 있으면 리턴 |
AI_ALL | AI_V4MAPPED 참조 |
AI_CANNAME | host가 NULL이 아닌 경우, NULL로 종료하는 공식 호스트명 포인트 리턴 |
AI_NUMERICHOST | host를 숫자로 이뤄진 주소 문자열로 해석하도록 강제 |
AI_NUMERICSERC | service를 숫자 포트 번호로 해석하도록 강제 |
AI_PASSIVE | 수동 접속에 적합한 소켓 구조체 리턴 |
AI_V4MAPPED | IPv6 주소를 발견하지 못하면 IPv4로 매핑된 주소를 리턴 |
2. addrinfo 리스트 해제 : freeaddrinfo()
getaddrinfo() 함수는 result가 가르키는 모든 구조체 메모리를 동적으로 할당한다.
getaddrinfo() 함수를 호출한 곳에서 해당 구조체를 사용하고 메모리 해제를 책임져야 한다.
#include <netdb.h>
void freeaddrinfo(struct addrinfo *result);
3. 에러 진단 : gai_strerror()
에러가 발생한 경우 아래 값 중에 하나를 에러코드로 리턴한다.
const char *gai_strerror(int errcode);
아래 에러 상수에 해당하는 문자열을 리턴
에러 상수 | 설명 |
EAI_ADDRFAMILY | hints.ai_family에 해당하는 호스트 주소가 없다 |
EAI_AGAIN | 이름 해석 일시 오류(나중에 다시 시도) |
EAI_BADFLAGS | hints.ai_flags에 잘못된 플레그 설정 |
EAI_FAIL | 이름 서버에 접속하면서 회복할 수 없는 실패가 생성 |
EAI_FAMILY | hints.family에 설정한 주소 패밀리를 지원할 수 없음. |
EAI_MEMORY | 메모리 할당 에러 |
EAI_NODATA | host에 해당하는 주소를 찾을 수 없음 |
EAI_NONAME | host나 service를 알수 없음. |
EAI_OVERFLOW | 인자 버퍼 오버플로우 |
EAI_SERVICE | hints.ai_socktype에 알맞은 service를 지원하지 않음. |
EAI_SOCKTYPE | hints.ai_socktype을 지원하지 않음. |
EAI_SYSTEM | errno로 시스템 에러를 리턴 |
4. getnameinfo() 함수
getaddrinfo() 함수와 정반대의 동작을 수행한다.
#include <netdb.h>
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
char *host, size_t hostlen, char *service, size_t servlen, int flags);
성공하면 '0'을 리턴, 에러가 발생하면 '0'이 아닌 값을 리턴
sockaddr 구조체를 통해 address 정보를 주면 host와 service에 대한 정보를 얻을 수 있다.
flags에 대한 자세한 내용은 아래 표를 참조
flags | 설명 |
NI_DGRAM | 데이터그램 소켓에 대한 정보를 리턴하도록 강제한다. |
NI_NAMEREQD | 호스트명을 찾을 수 없으면 숫자를 기본적으로 리턴하나 해당 플레그로 에러 리턴 |
NI_NOFQDN | 기본적으로 FQDN을 리턴, 호스트가 로컬일 경우만 FQDN의 첫 부분만 리턴 |
NI_NUMERICHOST | DNS 대신 host에 숫자 형식의 문자열을 리턴하도록 강제 |
NI_NUMERICSERV | 십진수 포트 번호를 리턴하도록 강제, /etc/services에 검색하지 않음. |
5. 구형 유사 함수
5.1. IP 주소를 얻어오는 함수
extern int h_errno;
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int type);
성공하면 hostent 구조체의 포인터를 리턴, 에러가 발생하면 NULL을 리턴
5.2. 포트 정보를 얻어오는 함수
/etc/services 파일에서 레코드를 가져오는 함수들이다.
struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
성공하면 servent구조체의 포인터를 리턴, 에러가 발생하면 NULL을 리턴
출처: http://chipmaker.tistory.com/entry/IP주소-및-포트-정보관련-시스템-함수 [CHIPMAKER]
'C++' 카테고리의 다른 글
[C++] OpenSSL을 이용한 간단한 echo 프로그래밍 (0) | 2017.11.27 |
---|---|
[C++] OpenSSL SSL_CTX관련 (0) | 2017.11.27 |
[C++11] std::regex를 사용해 보자. (0) | 2017.11.27 |
윈속 초기화 WSAStartup (0) | 2017.11.27 |
간단한 루프 병렬화(vs2017) (0) | 2017.11.12 |