域名和地址转换

来源:互联网 发布:淘宝售后多长时间关闭 编辑:程序博客网 时间:2024/06/05 04:52

    在连接服务器的时候,我们不一定要指定服务器的IP地址,可以指定它的域名,因此就需要将域名转换为IP地址的函数。

1、通过getaddrinfo()函数

#include<netdb.h>/***    hostname:要解析的主机域名或者IP*    service:主机的端口*    hints:要返回的信息种类*    result:返回的一系列解析结果的链表**/int getaddrinfo( const char *hostname, const char *service,                         const struct addrinfo *hints, struct addrinfo **result );                                                                   成功返回0,失败返回非0值
要掌握这个函数需要了解一下struct addrinfo;
struct addrinfo{     int   ai_flags;          //设置_PASSIVE表示可以接受任意地址或者端口    int   ai_family;          //地址族AF_INET(ipv4), AF_INET6(IPV6),AF_UNSPEC(任意的)     int    ai_socktype;     //socket类型,SOCK_STREAM(TCP), SOCK_DGRAM(UDP)    int    ai_protocol;       //默认0,或者IPPROTO_XXX    socklen_t   ai_addrlen;    //ai_addr的长度    char   *ai_canonname;    //    struct sockaddr  *ai_addr;     //socket  address for socket    struct addrinfo   *ai_next;     //链表中的下一个addrinfo节点}; 
在使用函数的过程中,自己根据自己的要求初始化一个addrinfo的结构体传进函数,并用一个addrinfo的指针去接受链表头指针,读取指针的ai_addr变量就可以得到解析后的IP地址。
    该函数的使用过程中需要结合以下两个函数:
1)void freeaddrinfo(struct addrinfo *addrList);                由于getaddrinfo()函数生成了链表,因此需要用这个函数对链表进行释放。2)const char*  gai_strerror(int arrorCode);                函数传进去getaddrinfo()失败时的数字,返回出错信息的字符串。
 以下的例子就是输入一个域名或者IP地址,最后打印IP地址的例子:
#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <arpa/inet.h>int main(int argc, char **argv){    if (argc != 2) {        printf("Usag...\n");        exit(1);    }    struct addrinfo hints;    struct addrinfo *res, *cur;    int ret;    struct sockaddr_in *addr;    char ipbuf[16];    memset(&hints, 0, sizeof(struct addrinfo));    hints.ai_family = AF_INET; /* Allow IPv4 */    hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */    hints.ai_protocol = 0; /* Any protocol */    hints.ai_socktype = SOCK_STREAM;           ret = getaddrinfo(argv[1], NULL,&hints,&res);        if (ret == -1) {        perror("getaddrinfo");        exit(1);    }        for (cur = res; cur != NULL; cur = cur->ai_next) {        addr = (struct sockaddr_in *)cur->ai_addr;        printf("%s\n", inet_ntop(AF_INET,             &addr->sin_addr, ipbuf, 16));    }    freeaddrinfo(res);    exit(0);}


 2、通过gethostbyname()函数
#include <netdb.h>/***    hostname:需要解析的域名或者IP地址*    返回hostent结构体指针**/struct hostent * gethostbyname(const char * hostname);struct hostent{    char * h_name;    char ** h_aliases;    char h_addrtype;    char h_length;    char ** h_addr_list;};
由于一个域名可能对应很多IP地址,因此保存解析后的IP地址是在一个二重指针h_addr_list中。
下面的例子显示了用法:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <arpa/inet.h>#include <netdb.h>int main(int argc, char *argv[]){    int i;    struct hostent *host;    if(argc < 2){        printf("Use : %s <hostname> \n", argv[0]);        exit(1);    }    host = gethostbyname(argv[1]);     for(i = 0; host‐>h_addr_list[i]; i++){        printf("IP addr %d : %s \n", i+1,        inet_ntoa(*(struct in_addr *)host‐>h_addr_list[i]));    }     return 0; }
上面代码中,打印IP地址是出现了令人困惑的类型转换。 host‐>h_addr_list[i] 得到的是字符串指针,但该字符串指针实际指向的是 struct in_addr 结构体变量地址值。 (struct in_addr *)host‐>h_addr_list[i] 将字符串指针转换为 struct in_addr 结构体指针。 由于 inet_ntoa 参数类型是 struct in_addr 而不是 struct in_addr * ,所以用 * 运算符取出 struct in_addr 结构体的值。
1 0
原创粉丝点击