gethostbyname, gethostbyaddr是不可重入函数;已经被getaddrinfo, getnameinfo替代
getaddrinfo 将主机和服务转换到socket地址,融合了函数getipnodebyname, getipnodebyaddr, getservbyname, getservbyport的功能,是可重入的
getnameinfo 功能与getaddrinfo相反,它将socket地址转换到主机和服务,融合了函数gethostbyaddr、getservbyport的功能,是可重入的
函数原型:
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
addrinfo 结构体定义如下:
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
函数参数说明:
node或service参数最多可能有一个为NULL。
node 要么为点分式地址(IPv4-点分十进制, IPv6-十六进制) 要么为主机名。如果hints.ai_flags包含了AI_NUMERICHOST标志,则node必须为数字地址。
service为端口号或者端口名。如果不为空,为端口名,则必须可以解析,通过/etc/services。
如果hints.ai_flags指定了AI_CANONNAME标志,则返回的结构体列表中第一个addrinfo结构体的ai_canonname域指向了主机的正式名字
如果hints.ai_flags指定了AI_PASSIVE标志,而且node为NULL,则返回的地址包含INADDR_ANY或IN6ADDR_ANY_INIT适合用来bind将要accept连接的socket。
如果hints.ai_flags指定了AI_PASSIVE标志,而且node不为NULL,则忽略AI_PASSIVE。
如果hints.ai_flags未指定AI_PASSIVE标志,则返回的地址适合用来connect,sendto,sendmsg。
如果hints.ai_flags未指定AI_PASSIVE标志,而且node为NULL, 则返回回环地址,用于本地服务。
根据node和service查找到对应的addr info。如果此信息被connect调用,则表示这是被监听对象;而监听者可以通过node里面设置。node如果是fe80这种IP V6地址,必须接%eth来指定接口,则监听者就是这个local IP;如果是raw socket,则监听端口就是hints里面的 ai_protocol。 getaddrinfo() supports the address%scope-id notation for specifying the IPv6 scope-ID.
int ip_to_hostname(const char* ip)
{
int ret = 0;
if(!ip)
{
printf("invalid params\n");
return -1;
}
struct addrinfo hints;
struct addrinfo *res, *res_p;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST;
hints.ai_protocol = 0;
ret = getaddrinfo(ip, NULL, &hints, &res);
if(ret != 0)
{
printf("getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
for(res_p = res; res_p != NULL; res_p = res_p->ai_next)
{
char host[1024] = {0};
ret = getnameinfo(res_p->ai_addr, res_p->ai_addrlen, host, sizeof(host), NULL, 0, NI_NAMEREQD);
if(ret != 0)
{
printf("getnameinfo: %s\n", gai_strerror(ret));
}
else
{
printf("hostname: %s\n", host);
}
}
freeaddrinfo(res);
return ret;
}
int hostname_to_ip(const char* hostname)
{
int ret = 0;
if(!hostname)
{
printf("invalid params\n");
return -1;
}
struct addrinfo hints;
struct addrinfo *res, *res_p;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
hints.ai_protocol = 0;
ret = getaddrinfo(hostname, NULL, &hints, &res);
if(ret != 0)
{
printf("getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
for(res_p = res; res_p != NULL; res_p = res_p->ai_next)
{
char host[1024] = {0};
ret = getnameinfo(res_p->ai_addr, res_p->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
if(ret != 0)
{
printf("getnameinfo: %s\n", gai_strerror(ret));
}
else
{
printf("ip: %s\n", host);
}
}
freeaddrinfo(res);
return ret;
}