Skip to content

C:getaddrinfo

Example

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc,char *argv[])
{
    int status;
    struct addrinfo hints;
    struct addrinfo *servinfo; // 결과를 저장할 변수
    memset(&hints, 0, sizeof(hints)); // hints 구조체의 모든 값을 0으로 초기화
    hints.ai_family = AF_UNSPEC; // IPv4와 IPv6 상관하지 않고 결과를 모두 받겠다
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
    status = getaddrinfo("www.google.com", "80", &hints, &servinfo);

    return 0;
}

Result

getaddrinfo 함수는 result가 가르키는 모든 구조체 메모리를 동적으로 할당한다. getaddrinfo함수를 호출한 곳에서 해당 구조체를 사용하고 메모리 해제를 책임져야 한다. addrinfo 리스트 메모리를 해제하기 위해 freeaddrinfo함수를 호출해야 한다.

FILES

  • /etc/hosts
  • /etc/host.conf
  • /etc/resolv.conf
  • /etc/gai.conf

Return value

이 함수는 성공하면 0을 반환하다. 실패하면 0이 아닌 값을 반환하는데, 아래 에러 값들중 하나를 반환하게 된다.

EAI_ADDRFAMILY
지정된 네트워크 호스트에 요청했던 address family 주소가 없는 경우이다. 예를들어 IPv4주소만 갖는 네트워크 호스트에게 'IPv6주소를 내놔라' 하고 요청한다면, 이런 에러가 반환된다.
EAI_AGAIN
nameserver가 일시적인 오류 표시를 반환했다. 일정 시간 이후에 다시 시도하라는 의미이다.
EAI_BADFLAGS
hints.ai_flags에 잘못된 플래그가 포함되어 있다. 또는 hints.ai_flags에는 AI_CANONNAME이 포함되었고 이름이 NULL인 경우이다.
EAI_FAIL
nameserver가 지속되는 오류 표시를 반환했다. EAI_AGAIN과는 달리 다시 시도해도 실패할 것이라는 의미다.
EAI_FAMILY
요청한 address family는 지원되지 않는다.
EAI_MEMORY
getaddrinfo를 수행하기에 메모리가 부족한 경우다. 거의 막장인 상황이다. kernel의 OOM killer가 제대로 작동하길 기대하면서 기다렸다가 일정 시간 지난 후 재시도 해보고 그래도 같은 에러를 받는다면 속편하게 재부팅 하라.
EAI_NODATA
지정한 네트워크 호스트가 있긴 한데... 네트워크 주소가 정의되어 있지 않은 경우다.
EAI_NONAME
노드 또는 서비스를 알 수 없다. 또는 노드와 서비스 모두가 NULL이다. 또는 AI_NUMERICSERV가 hints.ai_flags에 지정되었는데, 정작 service는 포트 번호를 나타내는 숫자형태의 문자열이 아니었다. 어떤 경우이건, 입력 매개변수를 잘못 넣었다는 의미다. 자신이 매개변수를 잘 넣었는지? 스스로의 코드를 다시 점검 해볼 것.
EAI_SERVICE
요청한 서비스를 요청한 소켓 유형에 사용할 수 없다. 다른 소켓 유형을 통해 사용할 수 있다. 예를 들어 서비스가 "쉘"(스트림 소켓에서만 사용할 수있는 서비스)이고 hints.ai_protocol이 IPPROTO_UDP이거나 hints.ai_socktype이 SOCK_DGRAM 인 경우 이 오류가 발생할 수 있다. 또는 서비스가 NULL이 아니고 hints.ai_socktype이 SOCK_RAW (서비스 개념을 지원하지 않는 소켓 유형) 인 경우 오류가 발생할 수 있습니다.
EAI_SOCKTYPE
요청한 소켓 유형이 지원되지 않는다. 예를 들어, hints.ai_socktype 및 hints.ai_protocol이 일치하지 않는 경우다. ai_socktype에는 SOCK_DGRAM 를 넣고, ai_protocol에는 IPPROTO_TCP를 넣은 hint를 입력 매개변수로 넘기면 발생할 수 있는 에러이다.
EAI_SYSTEM
위 모든 경우를 제외한 뭔가 다른 시스템 오류다, 골치아픈 경우다. 자세한 내용은 errno를 확인해야 하는 경우다.

반환값의 해석은

const char *gai_strerror(int errcode);

이 함수는 getaddrinfo( )가 return한 오류 코드를 사람이 읽을 수 있는 문자열로 변환해준다. 디버깅, 로그 출력 시 도움이 되니 참고할 것.

Troubleshooting

EAI_SERVICE

요청한 서비스를 요청한 소켓 유형에 사용할 수 없다. 서비스명은 https, smtp, ftp와 같은 것들이다. 이 내용을 조회하는 코드는 이 곳에서 참조할 수 있다. servname변수 사용위치를 확인하면 중간에, getservbyname를 사용하여 조회하는 것을 알 수 있다.

이 함수는 /etc/services파일의 내용을 확인한다. 이 파일이 없다면 만들어 줘야 한다. 데비안은 아래의 명령으로 추가할 수 있다.

$ sudo apt-get install netbase

See also

Favorite site