zoukankan      html  css  js  c++  java
  • 网络编程--名字与地址转换

    1.域名系统
    域名系统(Domain Name System,DNS)主要用于主机名与IP地址间的映射。主机名可以是简单名字,如solaris或bsdi,也可以是全限定域名FQDN(Fully Qualified Domain Name),如solaris.kohala.com
    1).资源记录
    DNS中的条目称为资源记录RR(resource record),一般感兴趣的有如下几个:
    • A           A记录将主机名映射为32位的IPv4地址。
    • AAAA     AAAA记录将主机名映射为128位的IPv6地址。
    • PTR        PTR记录(称为"指针记录")将IP地址映射为主机名。对于IPv4地址,32位地址的四个字节顺序反转,每个字节都转换成他的十进制ASCII值(0~255),然后附上in-addr.arpa,结果串用于PTR查询。对于IPv6地址,128位地址中的32个4位组顺序发转,每组被转换成相应的十六进制ASCII值(0~9, a~f),并附上ip6.int。
    • MX         MX记录指定一主机作为某主机的“邮件交换器”。
    • CNAME   CNAME代表“canonical name(规范名字)”,其常见的用法是为常用服务如ftp和www指派一个CNAME记录。
    2).解析器和名字服务器
    组织运行一个或多个名字服务器(name server), 它们通常就是所谓的BIND(Berkeley Internet Name Domain)程序。各种应用程序,如本书中我们编写的客户和服务器程序,通过调用称为解析器(resolver)的库中的函数来与DNS服务器联系。最常见的解析器函数是gethostbyname和gethostbyaddr。
    2.gethostbyname函数
    查找主机名最基本的函数是gethostbyname,如果调用成功,它就返回一个指向hostent的结构指针,该结构中含有所查找主机的所有IPv4地址,这个函数的局限是只能返回IPv4地址。
    #include <netdb.h>
    struct hostent *gethostbyname (const char *hostname);
    //返回:若成功为非空指针,出错为NULL其设置h_error
    本函数返回的空指针指向如下的hostent结构
    struct hostent {
       char  *h_name;       /* official (canonical) name of host */
       char **h_aliases;    /* pointer to array of pointers to alias names */
       int    h_addrtype;   /* host address type: AF_INET */
       int    h_length;     /* length of address: 4 */
       char **h_addr_list;  /* ptr to array of ptrs with IPv4 addrs */
    };
    按照DNS的说法,gethostbyname执行的是对A记录查询。它只能返回IPv4地址
    hostent结构如下所示
    gethostbyname与我们所介绍的其他套接口函数不同之处在于:当发生错误时,他不设置errno,而是将全局整数h_errno设置为定义在头文件<netdb.h>中的下列常值中的一个:
    • HOST_NOT_FOUND
    • TRY_AGAIN
    • NO_RECOVERTY
    • NO_DATA(等同于NO_ADDRESS)
    #include <netdb.h>
    #include <string.h>
    #include <stdio.h>
    #include <netdb.h>
    #include <string.h>
    #include <stdio.h>
    #include <sys/socket.h>
    
    int main(int argc,char* argv[]){
    
        if(argc<2){
            printf("Usage:./client hostname
    ");
            return -1;
        }
        struct hostent *ht=NULL;
        ht=gethostbyname(argv[1]);
        if(ht){
            int i=0;
            printf("get the host:%s addr
    ",argv[1]);
            printf("name:%s
    ",ht->h_name);
    
            printf("type:%s
    ",ht->h_addrtype==AF_INET?"AF_INET":"AF_INET6");
            printf("length:%d
    ",ht->h_length);
    
            for(i=0;;i++){
                if(ht->h_addr_list[i]!=NULL){
                    printf("IP:%s
    ",inet_ntoa((unsigned int *)ht->h_addr_list[i]));
                }else{
                    break;
                }
            }
    
            for(i=0;;i++){
                if(ht->h_aliases[i]!=NULL){
                    printf("alisa %d:%s
    ",i,ht->h_aliases[i]);
                }else{
                    break;
                }
            }
        }
        return 0;
    }
    3.gethostbyaddr函数
    gethostbyaddr函数试图有一个二进制的IP地址找到相应的主机名,与gethostbyname函数行为刚好相反
    #include <netdb.h>
    struct hostent *gethostbyaddr (const char *addr, socklen_t len, int family);
    //返回:成功为空指针,出错为NULL并设置h_errno
    本函数返回一个指向与之前所叙述一样的hostent结构的指针。
    参数addr实际上不是char *类型,而是一个指向存放IPv4地址的某个in_addr结构的指针;len参数是这个结构的大小:地域IPv4地址为4,family参数为AF_INET
    4.getservbyname和getservbyport函数
     1).像主机一样,服务也通常靠名字来认知,getservbyname函数用于根据给定名字查找相应服务,即:返回对应于给定服务名和协议名的相关服务信息(例如:端口号)
    #include <netdb.h>
    struct servent * 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, network-byte order */
      char   *s_proto;     /* protocol to use */
    };
    服务名servname必须指定,如果还指定了一个协议(即protoname为非空指针),则结果表项也必须有匹配的协议。
    servent结构中我们关心的主要字段是端口号。既然端口号是以网络字节序返回的,把它存储于套接口地址结构时绝对不能调用htons,对此函数的典型调用是:
    struct servent *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 */
    2).函数getservbyport用于给定端口号和可选协议查找相应服务
    struct servent *getservbyport (int port, const char *protoname);
    //返回:成功非空指针,出错为NULL
    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 fail */
    对于UDP,由于没有服务使用端口21,所以最后一个调用将失败。
  • 相关阅读:
    在Windows环境中使用版本管理工具Git [转]
    poj3630 Phone List **
    UVa10382 Watering Grass **
    软件项目计划书格式 [转]
    POI2001 Ants and the ladybug ***
    RMQ+1/1算法 [转]
    poj3264 Balanced Lineup *
    Windows Server 2003 出现的Service Unavailable怎么办?
    单车环佛山一环
    天凉了,大家多穿衣服
  • 原文地址:https://www.cnblogs.com/tla001/p/6608025.html
Copyright © 2011-2022 走看看