zoukankan      html  css  js  c++  java
  • UNIX网络编程——名字与地址转换(gethostbyname,gethostbyaddr,getservbyname,getservbyport,getaddrinfo,getnameinfo函数)

         名字和数值地址间进行转换的函数: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
    ", hptr->h_name);
    
                    for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
                            printf("	alias: %s
    ", *pptr);
    
                    switch (hptr->h_addrtype) {
                    case AF_INET:
                            pptr = hptr->h_addr_list;
                            for ( ; *pptr != NULL; pptr++)
                                    printf("	address: %s
    ",
                                            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
    ",pHost->h_name);
    
            char **pAliases = pHost->h_aliases;
            for(; NULL != *pAliases; pAliases++)
                    printf("aliases:%s
    ",*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
    ",inet_ntop(pHost->h_addrtype,*pAddrlist,str,sizeof(str)));
                    break;
            default:
                    printf("unknown type
    ");
                    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守护进程使用。

  • 相关阅读:
    37. VUE — webpack 基本使用
    36.VUE — 认识 Webpack 和 安装
    4. SpringBoot配置文件—YAML语法讲解
    3. IDEA 快速创建SpringBoot程序
    6. Maven 添加 镜像一些特性
    35. JS 模块化开发
    2. SPringBoot 解析HelloWorld 程序
    1. Maven 创建 SpringBoot项目 — HelloWorld — 我是踩了非常多的坑! 才写出来的 开学不顺 但是收获很多!!!
    34. VUE 的 编译作用域 以及 slot作用域插槽(获取组件作用域中的数据)
    【洛谷 3366】最小生成树_Kruskal
  • 原文地址:https://www.cnblogs.com/wangfengju/p/6172559.html
Copyright © 2011-2022 走看看