Socket的地址查询函数

http://blog.sina.com.cn/s/blog_988c054b010139e3.html

http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881693.html

包含头文件
#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——出错

addrinfo结构体原型

typedef struct addrinfo {
    int ai_flags;        //AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST
    int ai_family;        //AF_INET,AF_INET6
    int ai_socktype;    //SOCK_STREAM,SOCK_DGRAM
    int ai_protocol;    //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc.
    size_t ai_addrlen;            //must be zero or a null pointer
    char* ai_canonname;            //must be zero or a null pointer
    struct sockaddr* ai_addr;    //must be zero or a null pointer
    struct addrinfo* ai_next;    //must be zero or a null pointer
}

其中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
如上表所示,ai_flags的值范围为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当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串。

addrinfo结构中的ai_flags有以下几种值:

  • AI_ADDRCONFIG: 查询配置的地址类型(IPv4或IPv6).
  • AI_ALL: 查找IPv4和IPv6地址(仅用于AI_V4MAPPED).
  • AI_CANONNAME: 需要一个规范名(而不是别名).
  • AI_NUMERICHOST: 以数字格式返回主机地址.
  • AI_NUMERICSERV: 以端口号返回服务.
  • AI_PASSIVE: socket地址用于监听绑定.
  • AI_V4MAPPED: 如果没有找到IPv6地址, 则返回映射到IPv6格式的IPv6地址.

如果getaddrinfo失败, 不能使用perror或strerror来生成错误信息, 应该使用gai_strerror将返回的错误码转换成错误信息:

  • 原型: const char *gai_strerror(int error);
  • 头文件: <netdb.h>

int connect_2_server(char* host, int port, int verb, PLAYER_INTERRUPT_CBK interrupt_cbk)
{
    int  ret = 0;
    int  ai_port = 0;
    int  ai_family = 0;
#ifdef LINUX_OS
    char ai_host[INET6_ADDRSTRLEN] = {0};
#endif
    char portname[6];
    struct addrinfo *houts = NULL;
    struct addrinfo *ph = NULL;
    struct sockaddr_in* sinp = NULL;
    struct addrinfo hints;

hints.ai_flags = 0;
    hints.ai_family = 0;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_addrlen = 0;
    hints.ai_addr = NULL;
    hints.ai_canonname = NULL;
    hints.ai_next = NULL;
    sprintf(portname,"%d",port);
    if(getaddrinfo(host, portname, &hints, &houts)){
        printf("tcp: %s error, getaddrinfo return null\n",__FUNCTION__);
        return GX_TCP_ERROR_FATAL;
    }   
    ph = houts;

retry_host:
    if(ph == NULL){
        printf("cannot find hostname\n");
        freeaddrinfo(houts);
        return GX_TCP_ERROR_FATAL;
    }   
    sinp = (struct sockaddr_in*)ph->ai_addr;
    ai_family = ph->ai_family;
    ai_port = ntohs(sinp->sin_port);
    if(ai_port != port){
        printf("ai_port:%d port:%d\n",ai_port,port);
        ph = ph->ai_next;
        goto retry_host;
    }
#ifdef LINUX_OS
    if(inet_ntop(ph->ai_family,&sinp->sin_addr, ai_host, INET6_ADDRSTRLEN) == NULL){
        ph = ph->ai_next;
        printf("get addr %s\n",strerror(errno));
        goto retry_host;
    }
#endif

//printf("family is %s\n", (ai_family==AF_INET)?"AF_INET":"AF_INET6");
    //printf("host is %s\n", ai_host);
    //printf("port is %d\n", ai_port);
    ret = connect2server_with_af(ai_family,(struct sockaddr*)sinp, verb, interrupt_cbk);
    if(ret < 0){
        ph = ph->ai_next;
        goto retry_host;
    }

freeaddrinfo(houts);
    return ret;
}

getaddrinfo()函数详解的更多相关文章

  1. getaddrinfo()函数详解-(转自 cxz2009)

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

  2. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

  3. NSSearchPathForDirectoriesInDomains函数详解

    NSSearchPathForDirectoriesInDomains函数详解     #import "NSString+FilePath.h" @implementation ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. Linux C popen()函数详解

    表头文件 #include<stdio.h> 定义函数 FILE * popen( const char * command,const char * type); 函数说明 popen( ...

  6. kzalloc 函数详解(转载)

    用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0. view plain /** * kzal ...

  7. Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt

    PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...

  8. jQuery.attr() 函数详解

    一,jQuery.attr()  函数详解: http://www.365mini.com/page/jquery-attr.htm 二,jQuery函数attr()和prop()的区别: http: ...

  9. memset函数详解

    语言中memset函数详解(2011-11-16 21:11:02)转载▼标签: 杂谈 分类: 工具相关  功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的大 ...

随机推荐

  1. HDU 1698 just a hook 线段树,区间定值,求和

    Just a Hook Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1 ...

  2. ZeptoLab Code Rush 2015 C. Om Nom and Candies 暴力

    C. Om Nom and Candies Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/526 ...

  3. NOIP 2008 传纸条 NOIP 2000 方块取数 多线程DP

    思路都是一样,建立一个四维dp然后跑一发就完了 当然,也可以像我这么帅的人,降成三维再傻傻的跑一发啦啦啦~ #include<iostream> #include<stdio.h&g ...

  4. git命令行使用帮助

    克隆代码库 git clone git_project_url 提交代码 git commit -m 'commit messge'

  5. ios 得到目录大小 进率是1000

    - (CGFloat)folderSizeAtPath:(NSString *) folderPath {     NSFileManager * manager = [NSFileManager d ...

  6. android中反射机制

    本文介绍Android反射机制实现与原理,在介绍之前,要和Java进行比较,所以先看下Java中的反射相关知识: 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或 ...

  7. 【docker】 docker容器内部安装vi命令

    有时会需要在docker容器内使用vi命令,但是新启动的docker容器内并没有vi命令,那就需要自己安装一个 1.使用命令 apt-get update 2.进行安装 apt-get install ...

  8. 使用线程安全的 MSWeakTimer ,它不会对目标进行retain操作,避免循环引用

    MSWeakTimer 简易翻译:该timer没有runloop概念,线程安全,没有循环引用现象. https://github.com/mindsnacks/MSWeakTimer Descript ...

  9. VirtualBox 快捷键

    VirtualBox 的 Host 键是哪一个? 默认的 Host = Right Ctrl 组合键,意思是键盘上两个 “Ctrl”中右边的那个.键盘上是没有 “Right”这个键的,刚开始不明白,后 ...

  10. Ganglia开源集群监视项目

    Ganglia是UC Berkeley发起的一个开源集群监视项目,设计用于测量数以千计的节点.Ganglia的核心包含gmond.gmetad以及一个Web前端.主要 是用来监控系统性能,如:cpu ...