gethostbyname()、getaddrinfo()函数基本情况

gethostbyname()、getaddrinfo()函数基本情况1 gethostbynam 函数 struct hostent gethostbynam const char name 头文件 include

欢迎大家来到IT世界,在知识的湖畔探索吧!

gethostbyname()、getaddrinfo()函数基本情况

欢迎大家来到IT世界,在知识的湖畔探索吧!

1. gethostbyname

函数:struct hostent *gethostbyname(const char *name)

头文件 #include

返回hostent结构体类型指针:

struct hostent { char *h_name; /* official name of host */ char h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char h_addr_list; /* list of addresses */ }

欢迎大家来到IT世界,在知识的湖畔探索吧!

这个函数的局限是只能返回IPv4地址,并且不允许调用者指定所需地址类型的任何信息,返回的结构只包含了用于存储 IPv4 地址的空间。POSIX规范预警可能会在将来某个版本中撤销gethostbyname函数。

从POSIX规范中撤销该函数意在声明新的程序不该在使用它,鼓励在新的程序中改用getaddrinfo函数。

函数原型:

欢迎大家来到IT世界,在知识的湖畔探索吧!int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent result, int *h_errnop);

gethostbyname_r()函数是gethostbyname()函数的可重入版本,两个函数的功能是一样的。

2. gethostbyname2

函数:struct hostent *gethostbyname2(const char *name, int af);

它的工作原理类似于gethostbyname(),但是允许指定地址必须属于的地址族,当af参数为AF_INET时,gethostbyname2和gethostbyname一样,即查找并返回IPv4地址。当af参数为AF_INET6时,gethostbyname2只查找AAAA记录并且返回IPv6地址。

头文件:同上。

返回hostent结构体类型指针:同上。

函数原型:

int gethostbyname2_r(const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent result, int *h_errnop);

gethostbyname2_r()函数是gethostbyname2()函数的可重入版本,两个函数的功能是一样的。

3. getaddrinfo

函数将主机名、主机地址、服务名和端口的字符串表示转换成套接字地址结构体。它是已弃用的getgostbyname和getservbyname函数的新的替代品。和以前的那些函数不同,这个函数是可以重入的,适合于任何协议,函数把协议相关性完全隐藏在这个库函数内部。应用程序只要处理由getaddrinfo函数填写的套接口地址结构。

函数原型:

欢迎大家来到IT世界,在知识的湖畔探索吧!int getaddrinfo( const char *node, const char *service, const struct addrinfo *hints, struct addrinfo res);

1)nodename:节点名可以是主机名,也可以是数字地址。(IPV4的10进点分,或是IPV6的16进制);

2)servname:包含十进制数的端口号或服务名如(ftp,http);

3)hints:是一个空指针或指向一个addrinfo结构的指针,由调用者填写关于它所想返回的信息类型的线索;

4)res:存放返回addrinfo结构链表的指针;

头文件:

#include 
   
     #include 
    
      #include 
     
       void freeaddrinfo(struct addrinfo *res); const char *gai_strerror(int errcode); struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; } 
      
     
   

参数说明:

在getaddrinfo函数之前通常需要对以下6个参数进行以下设置:nodename、servname、hints的ai_flags、ai_family、ai_socktype、ai_protocol。在6项参数中,对函数影响最大的是nodename,sername和hints.ai_flag。而ai_family只是有地址为v4地址或v6地址的区别。而ai_protocol一般是为0不作改动。

其中ai_flags、ai_family、ai_socktype说明如下:

参数

取值

说明

ai_family

AF_INET

2

IPv4

AF_INET6

23

IPV6

AF_UNSPEC

0

协议无关

—-

—-

—-

ai_protocol

IPPROTO_IP

0

IP协议

IPPROTO_IPv4

4

IPv4

IPPROTO_IPv6

41

IPv6

IPPROTO_UDP

17

UDP

IPPROTO_TCP

6

TCP

—-

—-

ai_socktype

SOCK_STREAM

1

SOCK_DGRAM

2

数据报

—-

—-

ai_flags

AI_PASSIVE

1

被动的,用于bind,
通常用于 server socket

AI_CANONNAME

2

AI_NUMERICHOST

4

地址为数字串

对于ai_flags值的说明:

AI_PASSIVE

AI_CANONNAME

AI_NUMERICHOST

0/1

0/1

0/1

如上表所示,ai_flagsde值范围为0~7,取决于程序如何设置3个标志位,比如设置ai_flags为 “AI_PASSIVE|AI_CANONNAME”,ai_flags值就为3。

三个参数的含义分别为:

(1)AI_PASSIVE 当此标志置位时,表示调用者将在bind()函数调用中使用返回的地址结构。当此标志不置位时,表示将在connect()函数调用中使用。当节点名为NULL,且此标志置位,则返回的地址将是通配地址。如果节点名为NULL,且此标志不置位,则返回的地址将是回环地址。

(2)AI_CANNONAME当此标志置位时,在函数所返回的第一个addrinfo结构中的ai_cannoname成员中,应该包含一个以空字符结尾的字符串,字符串的内容是节点名的正规名。

(3)AI_NUMERICHOST当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串。

给定host和service(套接字地址的两个组成部分),getaddrinfo返回result, result是一个指向addrinfo结构的链表,其中每个结构体指向一个对应于host和service的套接字地址结构。

gethostbyname()、getaddrinfo()函数基本情况

在客户端调用了getaddrinfo之后,会遍历这个列表,一次尝试每一个套接字地址,直到调用socket和connect成功,建立起连接。类似地,服务器会尝试遍历列表中的每一个套接字的地址,直到调用socket和bind成功,描述符会被绑定到一个合法的套接字地址。为了避免内存泄漏,应用程序必须调用freeaddrinfo,释放该链表。如果getaddrinfo返回非零的错误代码,应用程序可以调用gai_streeror,将代码转成消息串。

getaddrinfo的host参数可以是域名,也可以是数字地址(如点分十进制IP地址)。service参数可以是服务名(如http),也可以是十进制端口号。如果不想把主机名转换成地址,可以把host设置为NULL。对service来说也是一样。但是必须指定两者中至少一个。

getaddrinfo一个很好的方面是addrinfo结构中的字段是不透明的,即它们可以直接传递给套接字接口中的函数,应程序代码无需再做任何处理。例如,ai_family、ai_socktype和ai_protocol可以直接传递给socket。类似的,ai_addr和ai_addrlen可以直接传递给connect和bind。这个强大的属性使得我们编写客户端和服务器能够独立于某一个特殊版本的IP协议。

4.关于上面几个函数线程安全如下表所示:

gethostbyname()、getaddrinfo()函数基本情况

gethostbyname处理数据时返回的结果是存储在一个静态结构体变量中的,作为本地的一个全局变量,只初始化一次,也就是说,下次对这个变量进行操作时,是基于这次的结果来操作的。

下面小例子说明这个问题:

欢迎大家来到IT世界,在知识的湖畔探索吧!ht1 = gethostbyname(“www.sohu.com”); ht2 = gethostbyname(“www.baidu.com”); printf("ip:%s\n",inet_ntop(ht1->h_addrtype,ht1->h_addr_list[i],str,30)); printf(":%s\n",ht1->h_aliases[i]); printf("IP:%s\n",inet_ntop(ht2->h_addrtype,ht2->h_addr_list[i],str,30)); printf("alias:%s\n",ht2->h_aliases[i]);
gethostbyname()、getaddrinfo()函数基本情况

ht1和ht2这个结构体指针在运行gethostbyname这个函数后指向的是同一个地址(即上面gethostbyname存储返回结果的变量地址)(大家可以在编译器里分部执行查看变量值的变化)

5.小结

应用程序用来把主机名转换成IP地址,gethostbyname是曾经常用的入口。随着向IPv6和线程化编程模型的转移,getaddrinfo显得更有用,因为它既解析IPv6地址,又符合线程安全。


免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/83164.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信