gethostbyname和gethostbyaddr这两个函数仅仅支持IPv4,getaddrinfo函数能够处理名字到地址以及服务到端口这两 种转换,返回的是一个sockaddr结构的链表而不是一个地址清单。这些sockaddr结构随后可由套接口函数直接使用。如此以 来,getaddrinfo函数把协议相关性安全隐藏在这个库函数内部。应用程序只要处理由getaddrinfo函数填写的套接口地址结构。该函数在 POSIX规范中定义了。

1. addrinfo结构定义在头文件netdb.h中:
struct addrinfo{

  int ai_flags; 

  int ai_family;                    //AF_INET、AF_INET6、UNIX etc 

  int ai_socktype;                //STREAM、DATAGRAM、RAW 

  int ai_protocol;                 //IPPROTO_IP、IPPROTO_IPV4、IPPROTO_IPV6 etc 

  size_t ai_addrlen;             //length of ai_addr 

  char* ai_canonname;        //full hostname 

  struct sockaddr* ai_addr;  //addr of host 

  struct addrinfo* ai_next;  

};

2.addrinfo结构
结构 固定的参数
typedef struct addrinfo {
int    ai_flags;
int    ai_family;
int    ai_socktype;
int             ai_protocol;
size_t                       ai_addrlen;
char                      * ai_canonname;
struct sockaddr     * ai_addr;
struct addrinfo      * ai_next;}
ai_addrlen must be zero or a null pointer
ai_canonname must be zero or a null pointer
ai_addr must be zero or a null pointer
ai_next must be zero or a null pointer
可以改动的参数
ai_flags:            AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST
ai_family:           AF_INET,AF_INET6
ai_socktype:     SOCK_STREAM,SOCK_DGRAM
ai_protocol:       IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc.

3 参数说明

在getaddrinfo函数之前通常需要对以下6个参数进行以下设置:nodename、servname、
hints ai_flags、ai_family、ai_socktype、ai_protocol
在6项参数中,对函数影响最大的是nodename,sername和hints.ai_flag
而ai_family只是有地址为IPv4地址或IPv6地址的区别。而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_NUMERICHOST AI_CANONNAME AI_PASSIVE
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当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串。
#include<netdb.h>

int getaddrinfo( const char *hostname,  const char *service,  const struct addrinfo *hints,  struct addrinfo **result );
返回0:  成功
非0:  出错

hostname: 一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
service:   一个服务名或者10进制端口号数串。
hints:     可以是一个空指针,也可以是一个指向某个addrinfo结构的指针,调用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定的服务既 支持TCP也支持UDP,那么调用者可以把hints结构中的ai_socktype成员设置成SOCK_DGRAM使得返回的仅仅是适用于数据报套接口 的信息。

本函数通过result指针参数返回一个指向addrinfo结构链表的指针,而addrinfo结构定义在头文件netdb.h中:

如果本函数返回成功,那么由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结构。这个连表中的所有结构以及它们指向的任何动态存储空间都被释放掉。

例子:
struct addrinfo *host_serv( const char *host, const char *serv, int family, int socktype )
{
    int n;
    struct   addrinfo  hints,  *res;

    bzero( &hints, sizeof(struct addrinfo) );
    hints.ai_flags = AI_CANONNAME;
    hints.ai_family = family;
    hints.ai_socktype = socktype;
  

 WSADATA dwRetval;
 if (WSAStartup(MAKEWORD(2,2),&dwRetval)!=0)      // Initialize Winsock

 {
   printf("WSAStartup failed.\n");
   return 1;
 }

if( (n = getaddrinfo( host, serv, &hints, &res ) ) != 0 )
       return (NULL);

    return ( res );
}

SOCK_STREAM 可靠的数据流
AF_UNSPEC 是ip4和ip6

getaddrinfo函数原型

函数 参数说明
int getaddrinfo(
const char* nodename
const char* servname,
const struct addrinfo* hints,//
struct addrinfo** res
);
nodename:节点名可以是主机名,也可以是数字地址。(IPV4的10进点分,或是IPV6的16进制)
servname:包含十进制数的端口号或服务名如(ftp,http)
hints:是一个空指针或指向一个addrinfo结构的指针,由调用者填写关于它所想返回的信息类型的线索。
res:存放返回addrinfo结构链表的指针

Getaddrinfo提供独立于协议的名称解析。

函数的前两个参数分别是节点名和服务名。节点名可以是主机名,也可以是地址串(IPv4的点分十进制数表示或IPv6的十六进制数字串)。服务名可以是十进制的端口号,也可以是已定义的服务名称,如ftp、http等。注意:其中节点名和服务名都是可选项,即节点名或服务名可以为NULL,此时调用的结果将取缺省设置,后面将详细讨论。
函数的第三个参数hints是addrinfo结构的指针,由调用者填写关于它所想返回的信息类型的线索。函数的返回值是一个指向addrinfo结构的链表指针res。

getaddrinfo的更多相关文章

  1. 解决 Error: getaddrinfo EADDRINFO 错误

    安装npm失败,提示Error: getaddrinfo EADDRINFO,原因在于虚拟机未连接互联网,悲剧.

  2. 网络编程之getaddrinfo

    IPv4中使用gethostbyname()函数完成主机名到地址解析,但是该API不允许调用者指定所需地址类型的任何信息,返回的结构只包含 了用于存储IPv4地址的空间.为了解决该问题,IPv6中引入 ...

  3. socket模块的getaddrinfo方法详解

    getaddrinfo方法用于通过url解析dns import sys,socket def dns_resolver(url): result = socket.getaddrinfo(url, ...

  4. Getaddrinfo()笔记

    WSADATA dwRetval; if (WSAStartup(MAKEWORD(2,2),&dwRetval)!=0) //开启Socket { printf("WSAStart ...

  5. getaddrinfo function

    The getaddrinfo function provides protocol-independent translation from an ANSI host name to an addr ...

  6. glibc resolv/res_send.c getaddrinfo() buffer stack smash when dealing malformation big DNS Response Package

    catalogue . 漏洞简述 . 调试环境搭建 . 漏洞利用 . 漏洞分析 . 缓解修复方案 1. 漏洞简述 0x1: 函数调用顺序 getaddrinfo (getaddrinfo.c) -&g ...

  7. libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)

    log报错如下: Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated w ...

  8. [第四版]用getaddrinfo设置tcp基本连接属性

    getaddrinfo getaddrinfo的一个重要功能, 很方便的构造struct sockaddr_in对象, 把繁琐的构造过程隐藏起来 getaddrinfo兼有gethostbyname和 ...

  9. 异常getaddrinfo enotfound

    在看NodeJS开发指南这本书时,书中的一个例子,讲解http.request的.代码如下: var http = require('http'); var querystring = require ...

随机推荐

  1. [moka同学笔记]YII2.0 判断签约状态,sql的两种查询方法

    方法一: //判断签约状态 $signed = 0; $sql="SELECT * from usho_community_sign_record WHERE com_id=$r->i ...

  2. HTML5的Server-Sent Events介绍

    body{ font: 16px/1.5em 微软雅黑,arial,verdana,helvetica,sans-serif; }       HTML5有一个Server-Sent Events(S ...

  3. android控制系统音量

    body_sb=(SeekBar)root.findViewById(R.id.body_sb);audioManager=(AudioManager)getActivity().getSystemS ...

  4. Django messages框架

    一.简介 在网页应用中,你经常需要在处理完表单或其它类型的用户输入后,显示一个通知消息(也叫做“flash message”)给用户 对于这个功能,Django 提供基于Cookie 和会话的消息,无 ...

  5. 静态代码审查工具FxCop插件开发(c#)

    FxCop是一款微软官方提供的.net平台代码审查工具,目的是检查我们编写的程序集的代码是否符合规范.FxCop默认提供的是微软默认的审查规则,而且该规则符合<Framework DesignG ...

  6. angular学习的一些小笔记(中)之ng-disabled轻松实现按钮是否可点击状态

    哇,这个可以轻松实现输入值就按钮可点击,输入框没有值则不可点击的状态呀 看代码 <!doctype html> <html ng-app=""> <h ...

  7. 酷!使用 jQuery & Canvas 制作相机快门效果

    在今天的教程中,我们将使用 HTML5 的 Canvas 元素来创建一个简单的摄影作品集,它显示了一组精选照片与相机快门的效果.此功能会以一个简单的 jQuery 插件形式使用,你可以很容易地整合到任 ...

  8. 前端优秀作品展示,JavaScript 版水果忍者

    <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版的切水果游戏由百度 JS 小组开发,采用 vml + svg 绘图,使用了 Rapha ...

  9. Swiper教程 —— 使用方法

    Swiper使用方法 1.首先加载插件,需要用到的文件有swiper.min.js和swiper.min.css文件. <!DOCTYPE html> <html> <h ...

  10. Flex Viewer(三)——Config的原理

    一.概述 在上文<深入浅出Flex Viewer(二)——体系结构>中,笔者详细介绍了到Flex Viewer框架,使得读者能够对该框架源代码的关键目录和文件结构和这些文件中所包含或涉及到 ...