- 浏览: 202864 次
- 性别:
- 来自: 重庆
文章分类
最新评论
1. 概述
IPv4中使用gethostbyname()函数完成主机名到地址解析,这个函数仅仅支持IPv4,且不允许调用者指定所需地址类型的任何信息,返回的结构只包含了用于存储IPv4地址的空间。IPv6中引入了getaddrinfo()的新API,它是协议无关的,既可用于IPv4也可用于IPv6。getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,返回的是一个addrinfo的结构(列表)指针而不是一个地址清单。这些addrinfo结构随后可由套接口函数直接使用。如此以来,getaddrinfo函数把协议相关性安全隐藏在这个库函数内部。应用程序只要处理由getaddrinfo函数填写的套接口地址结构。该函数在 POSIX规范中定义了。
2. 函数说明
包含头文件
#include<netdb.h>
函数原型
int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );
参数说明
hostname:一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
service:服务名可以是十进制的端口号,也可以是已定义的服务名称,如ftp、http等
hints:可以是一个空指针,也可以是一个指向某个addrinfo结构体的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定的服务既支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM使得返回的仅仅是适用于数据报套接口的信息。
result:本函数通过result指针参数返回一个指向addrinfo结构体链表的指针。
返回值:0——成功,非0——出错
3. 参数设置
在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不作改动。
getaddrinfo在实际使用中的几种常用参数设置
一般情况下,client/server编程中,server端调用bind(如果面向连接的还需要listen),client则不用掉bind函数,解析地址后直接connect(面向连接)或直接发送数据(无连接)。因此,比较常见的情况有
(1) 通常服务器端在调用getaddrinfo之前,ai_flags设置AI_PASSIVE,用于bind;主机名nodename通常会设置为NULL,返回通配地址[::]。
(2) 客户端调用getaddrinfo时,ai_flags一般不设置AI_PASSIVE,但是主机名nodename和服务名servname(更愿意称之为端口)则应该不为空。
(3) 当然,即使不设置AI_PASSIVE,取出的地址也并非不可以被bind,很多程序中ai_flags直接设置为0,即3个标志位都不设置,这种情况下只要hostname和servname设置的没有问题就可以正确bind。
上述情况只是简单的client/server中的使用,但实际在使用getaddrinfo和参考国外开源代码的时候,曾遇到一些将servname(即端口)设为NULL的情况(当然,此时nodename必不为NULL,否则调用getaddrinfo会报错)。
以下分情况进行了测试:
(1) 如果nodename是字符串型的IPv6地址,bind的时候会分配临时端口;
(2) 如果nodename是本机名,servname为NULL,则根据操作系统的不同略有不同,本文仅在WinXP和Win2003上作了测试。
a) WinXP系统(SP2)返回loopback地址[::1]
b) Win2003则将本机的所有IPv6地址列表加以返回。因为通常一台IPv6主机都有可能不止一个IPv6地址,比如fe80::1(本机 loopback地址)、fe80::***的Link-Local地址、3ffe:***的全局地址等等。这种情况下调用getaddrinfo会将这些地址全部返回,调用者应该注意如何使用这些地址。另外要注意的是,对于fe80::的地址在绑定的时候必须标明接口地址,即使用 fe80::20d:60ff:fe78:51c2%4或fe80::1%1这样的地址格式,通过getaddrinfo直接取出fe80地址好像无法直接bind。
4. 使用细节
如果本函数返回成功,那么由result参数指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo结构链表。可以导致返回多个addrinfo结构的情形有以下2个:
1. 如果与hostname参数关联的地址有多个,那么适用于所请求地址簇的每个地址都返回一个对应的结构。
2. 如果service参数指定的服务支持多个套接口类型,那么每个套接口类型都可能返回一个对应的结构,具体取决于hints结构的ai_socktype成员。
我们必须先分配一个hints结构,把它清零后填写需要的字段,再调用getaddrinfo,然后遍历一个链表逐个尝试每个返回地址。
getaddrinfo解决了把主机名和服务名转换成套接口地址结构的问题。
其中,如果getaddrinfo出错,那么返回一个非0的错误值。
#include<netdb.h>
const char *gai_strerror( int error );
该函数以getaddrinfo返回的非0错误值的名字和含义为他的唯一参数,返回一个指向对应的出错信息串的指针。
由getaddrinfo返回的所有存储空间都是动态获取的,这些存储空间必须通过调用freeaddrinfo返回给系统。
#include< netdb.h >
void freeaddrinfo( struct addrinfo *ai );
ai参数应指向由getaddrinfo返回的第一个addrinfo结构。这个连表中的所有结构以及它们指向的任何动态存储空间都被释放掉。
5. 例子
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s hostname\n", argv[1]); exit(1); } struct addrinfo *answer, hint, *curr; char ipstr[16]; bzero(&hint, sizeof(hint)); hint.ai_family = AF_INET; hint.ai_socktype = SOCK_STREAM; int ret = getaddrinfo(argv[1], NULL, &hint, &answer); if (ret != 0) { fprintf(stderr,"getaddrinfo: &s\n", gai_strerror(ret)); exit(1); } for (curr = answer; 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(answer); exit(0); }
发表评论
-
线程属性pthread_attr_t简介
2013-01-05 10:57 3868本文编辑整理自: http://hi.baidu.c ... -
避免内存碎片
2012-12-13 10:49 1449许多书籍提到过内存碎片,也看到一些方法防治内存 ... -
Linux程序设计中由线程使用不当引起的内存泄漏
2012-12-13 10:27 1360Linux程序设计中,创建线程时调用pthread_ ... -
EPOLL ET 模式下事件触发的场景
2012-09-25 10:13 1820ET模式称为边缘触发模式,顾名思义,不到边缘情况,是死都 ... -
惊群问题的思考
2012-09-25 10:13 908“据说”惊群问题已经是一个很古老的问题了,并且在大多数系统中已 ... -
linux惊群问题之udp
2012-09-25 10:12 1577今天测试udp服务器进程时发现log中记录了 ... -
Linux的mmap文件内存映射机制
2012-09-19 15:00 2286在讲述文件映 ... -
Berkeley DB 由浅入深【转自架构师杨建】
2012-09-19 15:00 1923在网上看到不少介绍Berkeley DB的文章,几乎 ... -
linux 多线程编程
2012-09-19 15:00 1464进程与线程 进程是程序执行时的一个实例 ... -
pthread_cond_wait()
2012-09-25 10:13 806/************pthread_cond_w ... -
linux下创建守护进程(daemon process)代码
2012-09-18 13:47 1602#include <stdio.h> ... -
dup and dup2的剖析
2012-09-18 13:35 632dup和dup2都可用来复制一个现存的文件描述符,使两个 ... -
C语言系统资源控制(getrlimit && setrlimit)
2012-09-18 11:52 931每一个进程都有自己的一组资源限制,在(*)inux系统中 ... -
UNIX缓冲机制
2012-09-18 11:11 980某日一朋友写了一个HELL ...
相关推荐
getaddrinfo.c 内部代码 getaddrinfo.c 内部代码 getaddrinfo.c 内部代码 getaddrinfo.c 内部代码
android Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated 97/100 android Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address ...
本文实例讲述了python中getaddrinfo()基本用法。分享给大家供大家参考。具体如下: import sys, socket result = socket.getaddrinfo("192.1.1.100", None) print result[0][4] print result 输出结果: ('172.20...
主要介绍了PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法,需要的朋友可以参考下
"getaddrinfo", a function that provides protocol-independent translation from an ANSI host name to an IP address written in C
适用于Android的getaddrinfo()测试 基于。 先决条件 使用SDK脚本创建独立的Android工具链: Android$ ./Sdk/ndk-bundle/build/tools/make_standalone_toolchain.py --arch arm --api 21 --install-dir ~/forge/...
Socket.getaddrinfo, 首先是从之前处理好的域名数据集中读取域名 其次循环挨个处理 做好异常处理 但是结果显然不尽如人意,但是当你手动将单个域名,放进去解析,是没有问题的。 然后我就蒙了,后来经过一圈的查阅...
这是一个基于getaddrinfo的DNS服务器。 如果您有一种不常见的方式来解析DNS并将其转换为适当的名称服务器,则很有用。 服务器本身会解析传入的DNS请求,查询getaddrinfo的IP地址,并使用这些地址制定有效的DNS响应...
还包括用于libc变体的getaddrinfo和getnameinfo包装器。 dns-lookup libc的一个小型包装程序,用于执行简单的DNS查找。 您可以使用lookup_host函数获取给定主机名的IP地址列表,并使用lookup_name函数获取给定IP地址...
主要介绍了VUE Error: getaddrinfo ENOTFOUND localhost,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
redis 连接报错 GET_LIKE_ERROR 处理过程.rar
主要是通过vc++内的mfc的Api实现,接口函数主要是:getnameinfo getaddrinfo函数显示
getaddrinfo.c 内部代码,开发APP获取CName,测试用例:www.microsoft.com www.baidu.com www.google.com
glibc库,getaddrinfo等函数的源码
使用socket库中的getaddrinfo函数批量将url转ip的脚本工具,简洁方便,省去了大量冗长的手工操作
DNS服务器超时时在不同系统上测试getaddrinfo()基础结构。 全面的分析,项目历史和技术背景在。 问题陈述 如果服务通过DNS解析并打开与依赖关系的连接,则依赖关系的不稳定DNS可以通过阻止与看似无辜的终结点(例如...
《python数据分析基础》第6.4 seaborn的第三个图“成对变量之间的散点图与单变量直方图” '''成对变量散点图和单变量直方图''' iris = sns.load_dataset('iris') sns.pairplot(iris) 在写这个代码时就存在一个疑惑...
SQL SERVER 2000数据库管理与开发
解决git clone时报错问题:sign_and_send_pubkey: signing failed: agent refused operation