当前位置:嗨网首页>书籍在线阅读

06-主机和服务转换函数概述

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

59.5 主机和服务转换函数概述

计算机以二进制形式来表示IP地址和端口号,但人们发现名字比数字更容易记忆。使用符号名还能有效地利用间接关系,用户和程序可以继续使用同一个名字,即使底层的数字值发生了变化也不会受到影响。

主机名和连接在网络上的一个系统(可能拥有多个IP地址)的符号标识符。服务名是端口号的符号表示。

主机地址和端口的表示有下列两种方法。

  • 主机地址可以表示为一个二进制值或一个符号主机名或展现格式(IPv4是点分十进制,IPv6是十六进制字符串)。
  • 端口号可以表示为一个二进制值或一个符号服务名。

格式之间的转换工作可以通过各种库函数来完成。本节将对这些函数进行简要的小结。下面几个小节将会详细描述现代API(inet_ntop()、inet_pton()、getaddrinfo()、getnameinfo()等)。在59.13节中将会简要地讨论一下被废弃的API(inet_aton()、inet_ntoa()、gethostbyname()、getservbyname()等)。

在二进制和人类可读的形式之间转换IPv4地址

inet_aton()和inet_ntoa()函数将一个IPv4地址在点分十进制表示形式和二进制表示形式之间进行转换。这里介绍这些函数的主要原因是读者在遗留代码中可能会看到这些函数。现在它们已经被废弃了。需要完成此类转换工作的现代程序应该使用接下来描述的函数。

在二进制和人类可读的形式之间转换IPv4和IPv6地址

inet_pton()和inet_ntop()与inet_aton()和inet_ntoa()类似,但它们还能处理IPv6地址。它们将二进制IPv4和IPv6地址转换成展现格式——即以点分十进制表示或十六进制字符串表示,或将展现格式转换成二进制IPv4和IPv6地址。

由于人类对名字的处理能力要比对数字的处理能力强,因此通常偶尔才会在程序中使用这些函数。inet_ntop()的一个用途是产生IP地址的一个可打印的表示形式以便记录日志。在有些情况下,最好使用这个函数而不是将一个IP地址转换(“解析”)成主机名,其原因如下。

  • 将一个IP地址解析成主机名可能需要向一台DNS服务器发送一个耗时较长的请求。
  • 在一些场景中,可能并不存在一个DNS(PTR)记录将IP地址映射到对应的主机名上。

本节在介绍执行二进制表示与对应的符号名之间的转换工作的getaddrinfo()和getnameinfo()之前(59.6节)先介绍这些函数主要是因为它们提供的更加简单的API,这样就能快速给出一些正常工作的使用Internet domain socket的例子。

主机和服务名与二进制形式之间的转换(已过时)

gethostbyname()函数返回与主机名对应的二进制IP地址,getservbyname()函数返回与服务名对应的端口号。对应的逆向转换是由gethostbyaddr()和getservbyport()来完成的。这里之所以要介绍这些函数是因为它们在既有代码中被广泛使用,但现在它们已经过时了。(SUSv3将这些函数标记为过时的,SUSv4删除了它们的规范。)新代码应该使用getaddrinfo()和getnameinfo()函数(稍后介绍)来完成此类转换。

主机和服务名与二进制形式之间的转换(现代的)

getaddrinfo()函数是gethostbyname()和getservbyname()两个函数的现代继任者。给定一个主机名和一个服务名,getaddrinfo()会返回一组包含对应的二进制IP地址和端口号的结构。与gethostbyname()不同,getaddrinfo()会透明地处理IPv4和IPv6地址。因此使用这个函数可以编写不依赖于IP版本的程序。所有新代码都应该使用getaddrinfo()来将主机名和服务名转换成二进制表示。

getnameinfo()函数执行逆向转换,即将一个IP地址和端口号转换成对应的主机名和服务名。

使用getaddrinfo()和getnameinfo()还可以在二进制IP地址与其展现格式之间进行转换。

在59.10节中讨论getaddrinfo()和getnameinfo()之前需要对DNS(59.8节)和/etc/services文件(59.9节)进行描述。DNS允许协作服务器维护一个将二进制IP地址映射到主机名和将主机名映射到二进制IP地址的分布式数据库。诸如DNS之类的系统的存在对于因特网的运转是非常关键的,因为对浩瀚的因特网主机名进行集中管理是不可能的。/etc/services文件将端口号映射到符号服务名。