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

UNIX网络编程——名字与地址转换(gethostbyname,gethostbyaddr,getservbyname,getservbyport,getaddrinfo,getnameinfo函数)

2013-07-26 10:53 204 查看
名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IPv4地址之间进行转换。getservbyname和getservbyport在服务器名字和端口号之间进行转换。还有两个协议无关的转换函数:getaddrinfo和getnameinfo,分别用于主机名字和IP地址之间以及服务名字和端口之间的转换。

1.gethostbyname函数

通过传入域名或者主机名,返回一个指向hostent结构的指针,该结构中含有所查找主机的所有IPv4地址。这个函数的局限是只能返回IPv4地址。

#include <netdb.h>
struct hostent *gethostbyname(const char *hostname)
本函数返回的非空指针指向如下的hostent结构。

struct hostent {
char  *h_name;            /* official name of host */
char **h_aliases;         /* alias list */
int    h_addrtype;        /* host address type */
int    h_length;          /* length of address */
char **h_addr_list;       /* list of addresses */
}


h_name为正式主机名

h_aliases为所有的别名

h_addrtype为AF_INET

h_length为4

h_addr_list为IPv4地址



#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#define MAX 100
int main(int argc, char **argv)
{
char                    *ptr, **pptr;
char                    str[MAX];
struct hostent  *hptr;

while (--argc > 0) {
ptr = *++argv;
if ( (hptr = gethostbyname(ptr)) == NULL) {
printf("gethostbyname error for host: %s: %s",
ptr, hstrerror(h_errno));
continue;
}
printf("official hostname: %s\n", hptr->h_name);

for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
printf("\talias: %s\n", *pptr);

switch (hptr->h_addrtype) {
case AF_INET:
pptr = hptr->h_addr_list;
for ( ; *pptr != NULL; pptr++)
printf("\taddress: %s\n",
inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
break;

default:
printf("unknown address type");
break;
}
}
exit(0);
}
运行结果:

huangcheng@ubuntu:~$ ./a.out www.a.shifen.com www.baidu.com
official hostname: www.a.shifen.com
address: 115.239.210.27
address: 115.239.210.26
official hostname: www.a.shifen.com
alias: www.baidu.com
address: 115.239.210.27
address: 115.239.210.26
即百度的正式主机名为: www.a.shifen.com;域名为:www.baidu.com
huangcheng@ubuntu:~$ ./a.out www.hikvision.com
official hostname: www.hikvision.com
address: 223.4.99.235


2.gethostbyaddr函数

gethostbyaddr函数试图由一个二进制的IP地址找到相应的主机名,与gethostbyname的行为刚好相反。

#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr,socklen_t len,int family);
addr参数实际上不是char *类型,而是一个指向存放IPv4地址的某个in_addr结构的指针(注意,这里不是简单的字符串,需要先将字符串形式的IP地址由inet_aton转化一下);len参数是这个结构的大小:对于IPv4地址为4。family参数为AF_INET。
#include<arpa/inet.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/utsname.h>
#include<stdlib.h>
#include<stdio.h>

int main()
{
struct hostent *pHost = NULL;
char str[100];
in_addr_t addr = inet_addr("192.168.2.103");
pHost = gethostbyaddr((char*)&addr,4,AF_INET);

/* struct utsname Name;
uname(&Name);
pHost = gethostbyname((char*)&Name);*/
printf("official hostname:%s\n",pHost->h_name);

char **pAliases = pHost->h_aliases;
for(; NULL != *pAliases; pAliases++)
printf("aliases:%s\n",*pAliases);

char **pAddrlist = NULL;
switch(pHost->h_addrtype)
{
case AF_INET:
case AF_INET6:
pAddrlist = pHost->h_addr_list;
for(; NULL != *pAddrlist; pAddrlist++)
printf("address:%s\n",inet_ntop(pHost->h_addrtype,*pAddrlist,str,sizeof(str)));
break;
default:
printf("unknown type\n");
break;
}

return 0;
}
运行结果:

huangcheng@ubuntu:~$ ./a.out
official hostname:ubuntu.local
address:192.168.2.103


3.getservbyname函数

像主机一样,服务也通常靠名字来认知。如果我们在程序代码中通过其名字而不是其端口号来指代一个服务,而且从名字到端口号的映射关系保存在一个文件中(通常是/etc/services),那么即使端口号发生变动,我们需需修改的仅仅是/etc/services文件中的某一行,而不必重新编译应用程序。getservbyname函数用于根据给定名字查找相应服务。

#include <netdb.h>
struct serven *getservbyname(const char *servname,const char protoname);
本函数返回的非空指针指向如下的servent结构:

struct servent {
char  *s_name;       /* official service name */
char **s_aliases;    /* alias list */
int    s_port;       /* port number */
char  *s_proto;      /* protocol to use */
}


服务名参数:servname 协议参数:protoname

servent结构中我们关心的主要字段是端口号。既然端口号是以网络字节序返回的,把它存放到套接字地址结构时绝对不能调用htons。

本函数的典型调用如下:

struct serven *sptr;
sptr = getservbyname("domain","udp");  /*DNS using UDP*/
sptr = getservbyname("ftp","tcp");  /*FTP using TCP */
sptr = getservbyname("ftp",NULL);  /*FTP using TCP"*/
sptr = getservbyname("ftp","udp");  /*this call will fail*/


既然FTP仅仅支持TCP,第二个调用和第三个调用等效,第四个调用则会失败。

4.getservbyport函数

getservbyport函数用于根据给定端口号和可选协议查找相应服务。

#include <netdb.h>
struct servent *getserbyport(int port,const char *protoname);
注意:参数port必须为网络字节序

本函数的典型调用如下:

struct servent *sptr;
sptr = getservbyport(htons(53),"udp");  /* DNS using UDP */
sptr = getservbyport(htons(21),"tcp");  /*FTP using TCP */
sptr = getservbyport(htons(21),NULL);  /* FTP using TCP */
sptr = getservbyport(htons(21),"udp");  /* this call will fial */
因为UDP上没有服务使用端口21,所以最后一个调用将失败。

必须清楚的是,有些端口号在TCP上用于一种服务,在UDP上却用于完全不同的另一个服务。例如:

huangcheng@ubuntu:~$ grep 514 /etc/services
shell           514/tcp         cmd             # no passwords used
syslog          514/udp
表明端口514在TCP上由rsh命令使用,在UDP上却由syslog守护进程使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐