getaddrinfo & getnameinfo

IPv4中使用gethostbyname()函数完成主机名到地址解析,这个函数仅仅支持IPv4,且不允许调用者指定所需地址类型的任何信息,返回的结构只包含了用于存储IPv4地址的空间。

IPv6中引入了getaddrinfo()的新API,它是协议无关的,既可用于IPv4也可用于IPv6。getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个addrinfo的结构(列表)指针而不是一个地址清单。

 

1. getaddrinfo函数原型:

 参数解析:

struct addrinfo{
    int ai_flags;	/*AI_PASSIVE,AI_CANONNAME*/
    int ai_family;	/*PF_xxx*/
    int ai_socktype;	/*SOCK_xxx*/
    int ai_protocol;	/*0 ir IPPROTO_xxx for IPV4 and IPV6*/
    size_t ai_addrlen;	/*length of ai_addr*/
    struct sockaddr *ai_addr;	/*binary address*/
    char *ai_canonname;	/*canonical name for hostname*/
    struct addrinfo *ai_next;	/*next structure in linked list*/
};
hints结构中调用者可以设置的成员有:

ai_flags       //0个或多个或在一起的AI_xxx值
ai_family    //AF_xxx
ai_socktype//SOCK_xxx
ai_protocol

详细如下图:

 函数使用:

#include<stdio.h>
#include<netdb.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<string.h>


int main(int argc, char * argv[])
{
	struct addrinfo *ai; 
	struct addrinfo *curr;
	struct addrinfo hint;
	char ipstr[16] = {0};   
	
	bzero(&hint, sizeof(hint)); //填充暗示信息
	hint.ai_family 		= AF_INET;
	hint.ai_socktype 	= SOCK_STREAM;
	hint.ai_flags 		= AI_CANONNAME;//告知返回主机规范名,若不告知,则不返回。

	
	if (getaddrinfo("sw2", NULL, &hint, &ai) == 0) //本系统主机名为 sw2
	{
		printf("ai->ai_family:%s \n",ai->ai_family == 2 ? "AF_INET" : "AF_INET6");	
		printf("ai->ai_socktype:%s \n",ai->ai_socktype == 1 ? "SOCK_STREAM" : (ai->ai_socktype == 2 ? "SOCK_DGRAM" : "SOCK_RAW"));
		printf("ai->ai_protocol:%d \n",ai->ai_protocol);
		printf("ai->ai_addrlen:%d \n",ai->ai_addrlen);
		printf("ai->ai_canonname:%s \n",ai->ai_canonname);
		printf("ai->ai_addr: \n");
		for (curr = ai; curr != NULL; curr = curr->ai_next) 
		{
			inet_ntop(AF_INET, &(((struct sockaddr_in *)(curr->ai_addr))->sin_addr), ipstr, 16);
			printf("%s\n", ipstr);
		}
			
		freeaddrinfo(ai);//由getaddrinfo返回的所有存储空间都是动态获取的,这些存储空间必须通过调用freeaddrinfo返回给系统。
	}
	
	return;
}

函数结果:

toney@sw2:~/study/network$ ./a.out 
ai->ai_family:AF_INET 
ai->ai_socktype:SOCK_STREAM 
ai->ai_protocol:6 
ai->ai_addrlen:16 
ai->ai_canonname:sw2 
ai->ai_addr: 
127.0.1.1

 

 

2. getnameinfo函数原型:

getnameinfo是getaddrinfo的互补函数,它是一个套接字地址为参数,返回其中的主机的一个字符串和描述其中服务的另一个字符串。
 

int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);

输入参数:
sockaddr指向一个套接字结构地址。

返回参数:
host:指定主机字符串。
serv:指定服务字符串。

如果调用者不想返回主机字符串或服务字符串,则指定hostlen或servlen为0.

flags该标志:

改变功能的默认操作的标志。默认情况下,应返回主机的完全限定域名(FQDN),但是:

如果设置了标志位NI_NOFQDN,则只应为本地主机返回FQDN的节点名称部分。
如果设置了标志位NI_NUMERICHOST ,则在所有情况下都应返回sa参数指向的套接字地址结构中包含的地址的数字形式而不是其名称。
如果设置了标志位NI_NAMEREQD,则如果找不到主机名,则应返回错误。
如果设置了标志位NI_NUMERICSERV,则在所有情况下都应返回服务地址的数字形式(例如,其端口号)而不是其名称。
如果设置了标志位NI_NUMERICSCOPE,则应返回范围标识符的数字形式(例如,接口索引)而不是其名称。如果sa参数不是IPv6地址,则应忽略此标志。
如果设置了标志位NI_DGRAM,则表明该服务是数据报服务(SOCK_DGRAM)。默认行为应假定该服务是流服务(SOCK_STREAM)。

 

函数使用:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
        int ret;
        char *ptr;
        char hostname[128] = {0};
        char servername[128] = {0};
        struct sockaddr_in addr_dst;

        ptr = "127.0.0.1";

        memset(&addr_dst,0,sizeof(addr_dst));
        addr_dst.sin_family = AF_INET;
        addr_dst.sin_addr.s_addr =  inet_addr(ptr);

        
        ret = getnameinfo((struct sockaddr *)&addr_dst, sizeof(addr_dst), hostname, sizeof(hostname), servername, sizeof(servername), 0);
        if (ret != 0)
        {
                printf("error in getnameinfo: %s \n", gai_strerror(ret));
        }
        else
        {
                printf("hostname IP: %s \n", hostname);
                printf("servername IP: %s \n", servername);
        }


        return;
}

函数结果:

toney@sw2:~/study/network$ ./a.out 
hostname IP: localhost 
servername IP: 0 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值