UNIX網絡編程——名字與地址轉換(gethostbyname,gethostbyaddr,getservbyname,getservbyport,getaddrinfo,getnameinfo函數)

     名字和數值地址間進行轉換的函數:gethostbyname和gethostbyaddr在主機名字與IPv4地址之間進行轉換。getservbyname和getservbyport在服務器名字和端口號之間進行轉換。還有兩個協議無關的轉換函數:getaddrinfo和getnameinfo,分別用於主機名字和IP地址之間以及服務名字和端口之間的轉換。shell


1.gethostbyname函數ubuntu

     經過傳入域名或者主機名,返回一個指向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爲全部的別名dom

           h_addrtype爲AF_INETsocket

           h_length爲4tcp

           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函數this

     gethostbyaddr函數試圖由一個二進制的IP地址找到相應的主機名,與gethostbyname的行爲恰好相反。spa

#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守護進程使用。
相關文章
相關標籤/搜索