您的位置:首页 > 理论基础 > 计算机网络

域名和地址转换

2016-05-05 17:39 323 查看
    在连接服务器的时候,我们不一定要指定服务器的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);
}
h
ost = 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 结构体的值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息