三、网络主机名和IP地址的对应关系
在做网络编程时经常要碰到的一个问题就是根据对方主机名来获取其IP地址,或者根据IP地址反过来解析主机名和其他信息。Linux提供了两个常用的API:
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr, int len, int type);
这两个函数失败时返回NULL且设置h_errno错误变量,调用hstrerror(h_errno)或者herror("Error");可以得到详细的出错信息。成功时均返回如下结构:
struct hostent {
char *h_name; /* 主机名*/
char **h_aliases; /* 主机别名的列表*/
int h_addrtype; /* 地址类型,AF_INET或其他*/
int h_length; /* 所占的字节数,IPv4地址都是4字节 */
char **h_addr_list; /* IP地址列表,网络字节序*/
}
#define h_addr h_addr_list[0] /*后向兼容 */
gethostbyname可以将机器名(如)转换为一个结构指针,gethostbyaddr可以将一个32位的IP地址(C0A80001)转换为结构指针。对于gethostbyaddr函数来说,输入参数“addr”的类型根据参数“type”来确定,目前type仅取AF_INET或AF_INET6。例如,type=2(即AF_INET),则addr就必须为struct in_addr{}类型。
继续看例子:
#include <stdio.h>
#include <netdb.h>
#include <error.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int arg,char** argv){
struct hostent *host,*host2;
if(NULL == (host = gethostbyname(argv[1]))){
herror("Error");
return 1;
}
printf("name = %s\n",host->h_name);
printf("aliases = %s\n",*host->h_aliases);
printf("add type = %d\n",host->h_addrtype);
printf("len = %d\n",host->h_length);
printf("IP=%s\n",inet_ntoa(*(struct in_addr*)host->h_addr));
printf("=================================\n");
struct in_addr maddr;
if(0 == inet_aton(argv[2],&maddr)){
return 0;
}
char* c = (char*)&maddr;
printf("org = %x.%x.%x.%x\n",*(c)&0xff,*(c+1)&0xff,*(c+2)&0xff,*(c+3)&0xff);
if(NULL == (host2 = gethostbyaddr(&maddr,4,2))){
printf("Error:%s\n",hstrerror(h_errno));
return 1;
}
printf("name = %s\n",host2->h_name);
printf("aliases = %s\n",*host2->h_aliases);
printf("add type = %d\n",host2->h_addrtype);
printf("len = %d\n",host2->h_length);
printf("IP=%s\n",inet_ntoa(*(struct in_addr*)host2->h_addr));
return 0;
}
运行结果如下:
当我们调用gethostbyaddr根据CU主页的IP地址获取其站点信息时返回的错误是“未知的主机”错误,原因留给大家自己思考吧。这充分说明对了于gethostbyname()函数和gethostbyaddr()函数的调用一定要判断其返回值。