728x90
getaddrinfo()
모든 프로토콜에 대해 호스트 이름, 호스트 주소, 포트 번호, 서비스 이름을 소켓 주소 구조체로 변환해준다. 즉, 네트워크 호스트 정보를 받아서 IP address를 가져오거나, 그 반대를 수행하는 함수이다. 특징으로는 멀티 쓰레딩시에 문제가 없고, IPv4나 IPv6 등 특정 IP protocol에 의존할 필요가 없다는 점이 있다.
int getaddrinfo(const char *host, /* Hostname or address */
const char *service, /* Port or service name */
const struct addrinfo *hints,/* Input parameters */
struct addrinfo **result); /* Output linked list */
/* 메모리 누수를 피하기 위해 addrinfo 구조체 리스트를 반환한다. */
void freeaddrinfo(struct addrinfo *result); /* Free linked list */
/* 에러 시에 에러 코드를 메세지로 바꿔준다. */
const char *gai_strerror(int errcode);
사용 예시
#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);
}
addrinfo 구조체 리스트
IP address와 호스트 이름을 표현한데 사용된다. 클라이언트는 이 리스트를 방문하면서 각각의 소켓 주소를 socket()과 connect()가 성공할 때까지 계속 테스트한다. 서버는 socket()과 bind()가 성공할 때까지 계속 테스트한다. 테스트에 성공하면 result에 그 소켓 주소 구조체를 가리키는 포인터를 반환한다.
struct addrinfo {
int ai_flags; /* Hints argument flags */
int ai_family; /* First arg to socket function */
int ai_socktype; /* Second arg to socket function */
int ai_protocol; /* Third arg to socket function */
char *ai_canonname; /* Canonical host name */
size_t ai_addrlen; /* Size of ai_addr struct */
struct sockaddr *ai_addr; /* Ptr to socket address structure */
struct addrinfo *ai_next; /* Ptr to next item in linked list */
};
getnameinfo
getaddrinfo의 반대 기능을 하는 함수로, 네트워크 주소 정보(소켓 주소 구조체, IP address)를 받아 그에 대응하는 호스트와 서비스 이름(도메인 주소)를 반환해준다. 즉, 32비트 IP address를 입력하면 dotted-decimal 주소나 도메인 이름을 반환한다.
int getnameinfo(const SA *sa, socklen_t salen, /* In: socket addr */
char *host, size_t hostlen, /* Out: host */
char *serv, size_t servlen, /* Out: service */
int flags); /* optional flags */
HOSTINFO 프로그램
도메인 이름을 main()의 인자로 넣었을 때, IP address로 반환한다.
#include "csapp.h"
int main(int argc, char **argv)
{
struct addrinfo *p, *listp, hints;
char buf[MAXLINE];
int rc, flags;
// getaddrinfo()를 사용해 addrinfo 리스트를 받는다.
memset(&hints, 0, sizeof(struct addrinfo)); // hint 구조체 초기화
hints.ai_family = AF_INET; /* IPv4의 주소만 반환해주세요 */
hints.ai_socktype = SOCK_STREAM; /* TCP 연결 */
if ((rc = getaddrinfo(argv[1], NULL, &hints, &listp)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(rc));
exit(1);
}
// getnameinfo()를 이용해 addrinfo 리스트에 있는 IP address들을 출력한다.
flags = NI_NUMERICHOST; /* 도메인 이름을 리턴하지 않고 10진수 주소 스트링을 대신 리턴한다. */
for (p = listp; p; p = p->ai_next) {
getnameinfo(p->ai_addr, p->ai_addrlen, // addrinfo 안의 IP주소(소켓 주소 구조체)를 찾아
buf, MAXLINE, // 호스트 이름. flag를 썼으니 10진수 주소로.
NULL, 0, // service는 안받아오는듯
flags);
printf("%s\n", buf); // input IP주소를 출력한다.
}
/* addrinfo 구조체를 free한다. */
freeaddrinfo(listp);
exit(0);
}
728x90
'컴퓨터 사이언스 > Network' 카테고리의 다른 글
tiny 서버 만들기 (0) | 2023.11.20 |
---|---|
웹 서버 기초 (0) | 2023.11.19 |
echo 클라이언트와 서버 (0) | 2023.11.19 |
소켓 인터페이스를 위해 도움을 주는 함수들 (0) | 2023.11.19 |
소켓 인터페이스 (0) | 2023.11.18 |