第6章 应用层¶
第 6 章 应用层¶
在前五章我们已经详细地讨论了计算机网络提供通信服务的过程。但是我们还没有讨论这些通信服务是如何提供给应用进程来使用的。本章讨论各种应用进程通过什么样的应用层协议来使用网络所提供的这些通信服务。
在上一章,我们已学习了运输层为应用进程提供了端到端的通信服务。但不同的网络应用的应用进程之间,还需要有不同的通信规则。因此在运输层协议之上,还需要有应用层协议 (application layer protocol)。这是因为,每个应用层协议都是为了解决某一类应用问题,而问题的解决又必须通过位于不同主机中的多个应用进程之间的通信和协同工作来完成。应用进程之间的这种通信必须遵循严格的规则。应用层的具体内容就是精确定义这些通信规则。具体来说,应用层协议应当定义:
互联网公共领域的标准应用的应用层协议是由 RFC 文档定义的,大家都可以使用。例如,万维网的应用层协议 HTTP(超文本传输协议)就是由建议标准 RFC 7230 定义的。如果浏览器开发者遵守 RFC 7230 标准,所开发出来的浏览器就能够访问任何遵守该标准的万维网服务器并获取相应的万维网页面。在互联网中还有很多其他应用的应用层协议不是公开的,而是专用的。例如,很多现有的 P2P 文件共享系统使用的就是专用应用层协议。
请注意,应用层协议与网络应用并不是同一个概念。应用层协议只是网络应用的一部分。例如,万维网应用是一种基于客户 / 服务器体系结构的网络应用。万维网应用包含很多部件,有万维网浏览器、万维网服务器、万维网文档的格式标准,以及一个应用层协议。万维网的应用层协议是 HTTP,它定义了在万维网浏览器和万维网服务器之间传送的报文类型、格式和序列等规则。而万维网浏览器如何显示一个万维网页面,万维网服务器是用多线程还是用多进程来实现,则都不是 HTTP 所定义的内容。
应用层的许多协议都是基于客户服务器方式。即使是 P2P 对等通信方式,实质上也是一种特殊的客户服务器方式。这里再明确一下,客户 (client) 和服务器 (server) 都是指通信中所涉及的两个应用进程。客户服务器方式所描述的是进程之间服务和被服务的关系。这里最主要的特征就是:客户是服务请求方,服务器是服务提供方。
下面先讨论许多应用协议都要使用的域名系统。在介绍了文件传送协议和远程登录协议后,再重点介绍万维网的工作原理及其主要协议。由于万维网的出现使互联网得到了飞速的发展,因此万维网在本章中占有最大的篇幅,也是本章的重点。接着讨论用户经常使用的电子邮件。最后,介绍有关网络管理方面的问题以及有关网络编程的基本概念。对应用层更深入的学习可参阅 [COME15][COME06][KURO17][TANE11] 及有关标准。
本章最重要的内容是:
(1) 域名系统 DNS—— 从域名解析出 IP 地址。
6.1 域名系统 DNS¶
6.1.1 域名系统概述¶
域名系统 DNS (Domain Name System) 是互联网使用的命名系统,用来把便于人们使用的机器名字转换为 IP 地址。域名系统其实就是名字系统。为什么不叫 “名字” 而叫 “域名” 呢?这是因为在这种互联网的命名系统中使用了许多的 “域”(domain),因此就出现了 “域名” 这个名词。“域名系统” 很明确地指明这种系统是用在互联网中的。
许多应用层软件经常直接使用域名系统 DNS。虽然计算机的用户只是间接而不是直接使用域名系统,但 DNS 却为互联网的各种网络应用提供了核心服务。
用户与互联网上某台主机通信时,必须要知道对方的 IP 地址。然而用户很难记住长达 32 位的二进制主机地址。即使是点分十进制 IP 地址也并不太容易记忆。但在应用层为了便于用户记忆各种网络应用,连接在互联网上的主机不仅有 IP 地址,而且还有便于用户记忆的主机名字。域名系统 DNS 能够把互联网上的主机名字转换为 IP 地址。
早在 ARPANET 时代,整个网络上只有数百台计算机,那时使用一个叫作 hosts 的文件,列出所有主机名字和相应的 IP 地址。只要用户输入一台主机名字,计算机就可很快地把这台主机名字转换成机器能够识别的二进制 IP 地址。
为什么机器在处理 IP 数据报时要使用 IP 地址而不使用域名呢?这是因为 IP 地址的长度是固定的 32 位(如果是 IPv6 地址,那就是 128 位,也是定长的),而域名的长度并不是固定的,机器处理起来比较困难。
从理论上讲,整个互联网可以只使用一个域名服务器,使它装入互联网上所有的主机名,并回答所有对 IP 地址的查询。然而这种做法并不可取。因为互联网规模很大,这样的域名服务器肯定会因过负荷而无法正常工作,而且一旦域名服务器出现故障,整个互联网就会瘫痪。因此,早在 1983 年互联网就开始采用层次树状结构的命名方法,并使用分布式的域名系统 DNS [RFC 1034, RFC 1035, STD13]。
互联网的域名系统 DNS 被设计成为一个联机分布式数据库系统,并采用客户服务器方式。DNS 使大多数名字都在本地进行解析 (resolve) \(^{①}\) ,仅少量解析需要在互联网上通信,因此 DNS 系统的效率很高。由于 DNS 是分布式系统,即使单个计算机出了故障,也不会妨碍整个 DNS 系统的正常运行。
域名到 IP 地址的解析是由分布在互联网上的许多域名服务器程序(可简称为域名服务器)共同完成的。域名服务器程序在专设的节点上运行,而人们也常把运行域名服务器程序的机器称为域名服务器。
域名到 IP 地址的解析过程的要点如下:当某一个应用进程需要把主机名解析为 IP 地址时,该应用进程就调用解析程序 (resolver),并成为 DNS 的一个客户,把待解析的域名放在 DNS 请求报文中,以 UDP 用户数据报方式发给本地域名服务器(使用 UDP 是为了减少开销)。本地域名服务器在查找域名后,把对应的 IP 地址放在回答报文中返回。应用进程获得目的主机的 IP 地址后即可进行通信。
若本地域名服务器不能回答该请求,则此域名服务器就暂时成为 DNS 中的另一个客户,并向其他域名服务器发出查询请求。这种过程直至找到能够回答该请求的域名服务器为止。上述这种查找过程,后面还要进一步讨论。
6.1.2 互联网的域名结构¶
早期的互联网使用了非等级的名字空间,其优点是名字简短。但当互联网上的用户数急剧增加时,用非等级的名字空间来管理一个很大的而且是经常变化的名字集合是非常困难的。因此,互联网后来就采用了层次树状结构的命名方法,就像全球邮政系统和电话系统那样。采用这种命名方法,任何一个连接在互联网上的主机或路由器,都有一个唯一的层次结构的名字,即域名 (domain name)。这里,“域”(domain) 是名字空间中一个可被管理的划分。域还可以划分为子域,而子域还可继续划分为子域的子域,这样就形成了顶级域、二级域、三级域,等等。
从语法上讲,每一个域名都由标号 (label) 序列组成,而各标号之间用点隔开(请注意,这里所说的 “点” 是英语中的句号 “.”,不是中文的句号 “。”)。例如下面的域名

就是中央电视台用于收发电子邮件的计算机(即邮件服务器)的域名,它由三个标号组成,其中标号 com 是顶级域名,标号 cctv 是二级域名,标号 mail 是三级域名。
DNS 规定,域名中的标号都由英文字母和数字组成,每一个标号不超过 63 个字符(但为了记忆方便,最好不要超过 12 个字符),也不区分大小写字母(例如,CCTV 或 cctv 在域名中是等效的)。标号中除连字符 (-) 外不能使用其他的标点符号。级别最低的域名写在最左边,而级别最高的顶级域名则写在最右边。由多个标号组成的完整域名总共不超过 255 个字符。DNS 既不规定一个域名需要包含多少个下级域名,也不规定每一级的域名代表什么意思。各级域名由其上一级的域名管理机构管理,而最高的顶级域名则由 ICANN 进行管理。用这种方法可使每一个域名在整个互联网范围内是唯一的,并且也容易设计出一种查找域名的机制。
需要注意的是,域名只是个逻辑概念,并不代表计算机所在的物理地点。变长的域名和使用有助记忆的字符串,是为了便于人使用。而 IP 地址是定长的 32 位二进制数字则非常便于机器进行处理。这里需要注意,域名中的 “点” 和点分十进制 IP 地址中的 “点” 并无一一对应的关系。点分十进制 IP 地址中一定是包含三个 “点”,但每一个域名中 “点” 的数
目则不一定正好是三个。
截至 2020 年 6 月的统计 [W-Wiki],现在全球顶级域名 TLD (Top Level Domain) 在 IANA 登记的已有 1584 个(其中有不到 80 个未使用)。原先的顶级域名共分为三大类:
(1) 国家顶级域名 nTLD: 采用 ISO 3166 的规定。如: cn 表示中国,us 表示美国,uk 表示英国,等等 \(^{①}\) 。国家顶级域名又常记为 ccTLD(cc 表示国家代码 country-code)。截至 2020 年 6 月为止,国家顶级域名总数已达 316 个。
(2) 通用顶级域名 gTLD: 到 2006 年 12 月为止,通用顶级域名的总数已经达到 20 个。最先确定的通用顶级域名有 7 个,即:
com(公司企业),net(网络服务机构),org(非营利性组织),int(国际组织),edu(美国专用的教育机构),gov(美国的政府部门),mil 表示(美国的军事部门)。
以后又陆续增加了 13 个通用顶级域名:
aero(航空运输企业),asia(亚太地区),biz(公司和企业),cat(使用加泰隆人的语言和文化团体),coop(合作团体),info(各种情况),jobs(人力资源管理者),mobi(移动产品与服务的用户和提供者),museum(博物馆),name(个人),pro(有证书的专业人员),tel(Telnic 股份有限公司),travel(旅游业)。
(3) 基础结构域名 (infrastructure domain): 这种顶级域名只有一个,即 arpa,用于反向域名解析,因此又称为反向域名。
值得注意的是,ICANN 于 2011 年 6 月 20 日在新加坡会议上正式批准新顶级域名(New gTLD),因此任何公司、机构都有权向 ICANN 申请新的顶级域名。新顶级域名的后缀特点,使企业域名具有了显著的、强烈的标志特征。因此,新顶级域名被认为是真正的企业网络商标。新顶级域名是企业品牌战略发展的重要内容,其申请费很高(18 万美元),并且在 2013 年开始启用。目前已有一些由两个汉字组成的中文的顶级域名出现了,例如,商城、公司、新闻等。然而中文顶级域名并未获得广泛的使用(可能是使用不太方便吧)。
在国家顶级域名下注册的二级域名均由该国家自行确定。例如,顶级域名为 jp 的日本,将其教育和企业机构的二级域名定为 ac 和 co,而不用 edu 和 com。
我国把二级域名划分为 “类别域名” 和 “行政区域名” 两大类。
“类别域名” 共 7 个,分别为:ac(科研机构),com(工、商、金融等企业),edu(中国的教育机构),gov(中国的政府机构),mil(中国的国防机构),net(提供互联网络服务的机构),org(非营利性的组织)。
“行政区域名” 共 34 个,适用于我国的各省、自治区、直辖市。例如:bj(北京市),js(江苏省),等等。
关于我国的互联网络发展现状以及各种规定(如申请域名的手续),均可在中国互联网网络信息中心 CNNIC 的网址上找到 [W-CNNIC]。
用域名树来表示互联网的域名系统是最清楚的。图 6-1 是互联网域名空间的结构,它实际上是一个倒过来的树,在最上面的是根,但没有对应的名字。根下面一级的节点 \(^{①}\) 就是最高一级的顶级域名(由于根没有名字,所以在根下面一级的域名就叫作顶级域名)。顶级域名可往下划分子域,即二级域名。再往下划分就是三级域名、四级域名,等等。图 6-1 列举了一些域名作为例子。凡是在顶级域名 com 下注册的单位都获得了一个二级域名。图中给出的例子有:中央电视台 cctv,以及 IBM 和华为等公司。在顶级域名 cn(中国)下面举出了几个二级域名,如:bj, edu 以及 com。在某个二级域名下注册的单位就可以获得一个三级域名。图中给出的在 edu 下面的三级域名有:tsinghua(清华大学)和 pku(北京大学)。一旦某个单位拥有了一个域名,它就可以自己决定是否要进一步划分其下属的子域,并且不必由其上级机构批准。图中 cctv(中央电视台)和 tsinghua(清华大学)都分别划分了自己的下一级的域名 mail 和 www(分别是三级域名和四级域名) \(^{②}\) 。域名树的树叶就是单台计算机的名字,它不能再继续往下划分子域了。

应当注意,虽然中央电视台和清华大学都各有一台计算机取名为 mail,但它们的域名并不一样,因为前者是 mail.cctv.com,而后者是 mail.tsinghua.edu.cn。因此,即使在世界上还有很多单位的计算机取名为 mail,但是它们在互联网中的域名都必须是唯一的。
这里还要强调指出,互联网的名字空间是按照机构的组织来划分的,与物理的网络无关,与 IP 地址中的 “子网” 也没有关系。
6.1.3 域名服务器¶
上面讲述的域名体系是抽象的。但具体实现域名系统则是使用分布在各地的域名服务器。从理论上讲,可以让每一级的域名都有一个相对应的域名服务器,使所有的域名服务器构成和图 6-1 相对应的 “域名服务器树” 的结构。但这样做会使域名服务器的数量太多,使域名系统的运行效率降低。因此 DNS 就采用划分区的办法来解决这个问题。
一个服务器所负责管辖的(或有权限的)范围叫作区 (zone)。各单位根据具体情况来划分自己管辖范围的区。但在一个区中的所有节点必须是能够连通的。每一个区设置相应的权限域名服务器 (authoritative name server),用来保存该区中的所有主机的域名到 IP 地址的映射。总之,DNS 服务器的管辖范围不是以 “域” 为单位,而是以 “区” 为单位的。区是 DNS 服务器实际管辖的范围。区可能等于或小于域,但一定不能大于域。
图 6-2 是区的不同划分方法的举例。假定 abc 公司有下属部门 x 和 y,部门 x 下面又分三个分部门 u, v 和 w,而 y 下面还有其下属部门 t。图 6-2 (a) 表示 abc 公司只设一个区 abc.com。这时,区 abc.com 和域 abc.com 指的是同一件事。但图 6-2 (b) 表示 abc 公司划分了两个区(大的公司可能要划分多个区):abc.com 和 y.abc.com。这两个区都隶属于域 abc.com,都各设置了相应的权限域名服务器。不难看出,区是 “域” 的子集。


图 6-3 以图 6-2 (b) 中公司 abc 划分的两个区为例,给出了 DNS 域名服务器树状结构图。这种 DNS 域名服务器树状结构图可以更准确地反映出 DNS 的分布式结构。在图 6-3 中的每一个域名服务器都能够进行部分域名到 IP 地址的解析。当某个 DNS 服务器不能进行域名到 IP 地址的转换时,它就设法找互联网上别的域名服务器进行解析。

从图 6-3 可看出,互联网上的 DNS 域名服务器也是按照层次安排的。每一个域名服务器都只对域名体系中的一部分进行管辖。根据域名服务器所起的作用,可以把域名服务器划分为以下四种不同的类型:
(1) 根域名服务器 (root name server): 根域名服务器是最高层次的域名服务器,也是最重要的域名服务器。所有的根域名服务器都知道所有的顶级域名服务器的域名和 IP 地址。根域名服务器是最重要的域名服务器,因为不管是哪一个本地域名服务器,若要对互联网上任何一个域名进行解析 (即转换为 IP 地址), 只要自己无法解析,就首先要求助于根域名服务器。假定所有的根域名服务器都瘫痪了,那么整个互联网中的 DNS 系统就无法工作。全世界的根域名服务器只使用 13 个不同 IP 地址的域名,即 a.rootservers.net, b.rootservers.net, …, m.rootservers.net。每个域名下的根域名服务器由专门的公司或美国政府的某个部门负责运营。但请注意,虽然互联网的根域名服务器总共只有 13 个域名,但根域名服务器并非仅由 13 台机器所组成(如果仅仅依靠这 13 台机器,根本不可能为全世界的互联网用户提供令人满意的服务)。实际上,在互联网中是由 13 套装置(13 installations,也就是 13 套系统)构成这 13 组根域名服务器的 [W-ROOT]。每一套装置在很多地点安装根域名服务器(也可称为镜像根服务器),但都使用同一个域名。负责运营根域名服务器的公司大多在美国,但所有的根域名服务器却分布在全世界。为了提供更可靠的服务,在每一个地点的根域名服务器往往由多台机器组成(为了安全起见,这些根域名服务器的具体位置是严格保密的,不对外开放参观)。现在世界上大部分 DNS 域名服务器,都能就近找到一个根域名服务器查询 IP 地址(现在这些根域名服务器都已增加了 IPv6 地址)。为了方便,人们常用从 A 到 M 的前 13 个英文字母中的一个,来表示某组根域名服务器。截至 2021 年 3 月 24 日,全球共有 1375 个根域名服务器在运行,其中在我国的共有 37 个(分布在北京 (8 个)、上海、杭州 (2 个)、武汉 (2 个)、贵阳、重庆、广州、西宁 (3 个)、郑州 (2 个)、香港 (7 个)、澳门 (2)、台北 (7 个))。
由于根域名服务器采用了任播 (anycast) 技术 \(^{①}\) ,因此当 DNS 客户向某个根域名服务器的 IP 地址发出查询报文时,互联网上的路由器就能找到离这个 DNS 客户最近的一个根域名服务器。这样做不仅加快了 DNS 的查询过程,也更加合理地利用了互联网的资源。
必须指出,目前根域名服务器在全球的分布仍然是很不均衡的。在某些地区根域名服务器还较少,这就影响了上网的速率。
需要注意的是,在许多情况下,根域名服务器并不直接把待查询的域名直接转换成 IP 地址(根域名服务器也没有存放这种信息),而是告诉本地域名服务器下一步应当找哪一个顶级域名服务器进行查询。
由于根域名服务器在 DNS 中的地位特殊,因此对根域名服务器有许多具体的要求,如必须能够运行某些程序等 [RFC7720]。
(2) 顶级域名服务器(即 TLD 服务器):这些域名服务器负责管理在该顶级域名服务器注册的所有二级域名。当收到 DNS 查询请求时,就给出相应的回答(可能是最后的结果,也可能是下一步应当找的域名服务器的 IP 地址)。
(3) 权限域名服务器:这就是前面已经讲过的负责一个区的域名服务器。当一个权限域名服务器还不能给出最后的查询回答时,就会告诉发出查询请求的 DNS 客户,下一步应当找哪一个权限域名服务器。例如在图 6-2 (b) 中,区 abc.com 和区 y.abc.com 各设有一个权限域名服务器。
(4) 本地域名服务器 (local name server): 本地域名服务器并不属于图 6-3 所示的域名服务器层次结构,但它对域名系统非常重要。当一台主机发出 DNS 查询请求时,这个查询请求报文就发送给本地域名服务器。由此可看出本地域名服务器的重要性。每一个互联网服务提供者 ISP,或一个大学,甚至一个大学里的系,都拥有一个本地域名服务器,本地域名服务器离用户较近,一般不超过几个路由器的距离。当所要查询的主机也属于同一个本地 ISP 时,该本地域名服务器立即就能将所查询的主机名转换为它的 IP 地址,而不需要再去询问其他的域名服务器。
为了提高域名服务器的可靠性,DNS 域名服务器都把数据复制到几个域名服务器来保存,其中的一个是主域名服务器 (master name server),其他的是辅助域名服务器 (secondary name server)。当主域名服务器出故障时,辅助域名服务器可以保证 DNS 的查询工作不会中断。主域名服务器定期把数据复制到辅助域名服务器中,而更改数据只能在主域名服务器中进行。这样就保证了数据的一致性。
下面简单讨论一下域名的解析过程。这里要注意两点。
第一,主机向本地域名服务器的查询一般都采用递归查询 (recursive query)。所谓递归查询就是:如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户的身份,向其他根域名服务器继续发出查询请求报文(即替该主机继续查询),而不是让该主机自己进行下一步的查询。因此,递归查询返回的查询结果或者是所要查询的 IP 地址,或者是报错,表示无法查询到所需的 IP 地址。
第二,本地域名服务器向根域名服务器的查询通常采用迭代查询 (iterative query)。迭代查询的特点是这样的:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉本地域名服务器:“你下一步应当向哪一个域名服务器进行查询”。然后让本地域名服务器进行后续的查询(而不是替本地域名服务器进行后续的查询)。根域名服务器通常是把自己知道的顶级域名服务器的 IP 地址告诉本地域名服务器,让本地域名服务器再向顶级域名服务器查询。顶级域名服务器在收到本地域名服务器的查询请求后,要么给出所要查询的 IP 地址,要么告诉本地域名服务器下一步应当向哪一个权限域名服务器进行查询,本地域名服务器就这样进行迭代查询。最后,知道了所要解析的域名的 IP 地址,然后把这个结果返回给发起查询的主机。当然,本地域名服务器也可以采用递归查询,这取决于最初的查询请求报文的设置要求使用哪一种查询方式。
图 6-4 用例子说明了这两种查询的区别。

假定域名为 m.xyz.com 的主机想知道另一台主机(域名为 y.abc.com)的 IP 地址。例如,主机 m.xyz.com 打算发送邮件给主机 y.abc.com。这时就必须知道主机 y.abc.com 的 IP 地址。下面是图 6-4 (a) 的几个查询步骤:
我们注意到,这 8 个步骤总共要使用 8 个 UDP 用户数据报的报文。本地域名服务器经过三次迭代查询后,从权限域名服务器 dns.abc.com 得到了主机 y.abc.com 的 IP 地址,最后把结果返回给发起查询的主机 m.xyz.com。
图 6-4 (b) 是本地域名服务器采用递归查询的情况。在这种情况下,本地域名服务器只需向根域名服务器查询一次,后面的几次查询都是在其他几个域名服务器之间进行的(步骤③至⑥)。只是在步骤⑦,本地域名服务器从根域名服务器得到了所需的 IP 地址。最后在步骤⑧,本地域名服务器把查询结果告诉主机 m.xyz.com。整个的查询也是使用 8 个 UDP 报文。
为了提高 DNS 查询效率,并减轻根域名服务器的负荷和减少互联网上的 DNS 查询报文数量,在域名服务器中广泛地使用了高速缓存(有时也称为高速缓存域名服务器)。高速缓存用来存放最近查询过的域名以及从何处获得域名映射 \(^{①}\) 信息的记录。
例如,在图 6-4 (a) 的查询过程中,如果在不久前已经有用户查询过域名为 y.abc.com 的 IP 地址,那么本地域名服务器就不必向根域名服务器重新查询 y.abc.com 的 IP 地址,而是直接把高速缓存中存放的上次查询结果(即 y.abc.com 的 IP 地址)告诉用户。
假定本地域名服务器的缓存中并没有 y.abc.com 的 IP 地址,而是存放着顶级域名服务器 dns.com 的 IP 地址,那么本地域名服务器也可以不向根域名服务器进行查询,而是直接向 com 顶级域名服务器发送查询请求报文。这样不仅可以大大减轻根域名服务器的负荷,而且也能够使互联网上的 DNS 查询请求和回答报文的数量大为减少。
由于名字到地址的绑定 \(^{②}\) 并不经常改变,为保持高速缓存中的内容正确,域名服务器应为每项内容设置计时器并处理超过合理时间的项目(例如,每个项目只存放两天)。当域名服务器已从缓存中删去某项信息后又被请求查询该项信息,就必须重新到授权管理该项的域名服务器中获取绑定信息。当权限域名服务器回答一个查询请求时,在响应中都指明绑定有效存在的时间值。增加此时间值可减少网络开销,而减少此时间值可提高域名转换的准确性。
不但在本地域名服务器中需要高速缓存,在主机中也很需要。许多主机在启动时从本地域名服务器下载名字和地址的全部数据库,维护存放自己最近使用的域名的高速缓存,并且只在从缓存中找不到名字时才使用域名服务器。维护本地域名服务器数据库的主机自然应该定期地检查域名服务器以获取新的映射信息,而且主机必须从缓存中删掉无效的项。由于域名改动并不频繁,大多数网点不需花太多精力就能维护数据库的一致性。
6.2 文件传送协议¶
6.2.1 FTP 概述¶

文件传送协议 FTP (File Transfer Protocol) [RFC 959, STD9] 曾是互联网视频讲解上使用得最广泛的文件传送协议。FTP 提供交互式的访问,允许客户指明文件的类型与格式(如指明是否使用 ASCII 码),并允许文件具有存取权限(如访问文件的用户必须经过授权,并输入有效的口令)。FTP 屏蔽了各计算机系统的细节,因而适合于在异构网络中任意计算机之间传送文件。
在互联网发展的早期阶段,用 FTP 传送文件约占整个互联网的通信量的三分之一,而由电子邮件和域名系统所产生的通信量远小于 FTP 所产生的通信量。只是到了 1995 年,WWW 的通信量才首次超过了 FTP。
在下面 6.2.2 和 6.2.3 节分别介绍基于 TCP 的 FTP 和基于 UDP 的简单文件传送协议 TFTP,它们都是文件共享协议中的一大类,即复制整个文件,其特点是:若要存取一个文件,就必须先获得一个本地的文件副本。如果要修改文件,只能对文件的副本进行修改,然后再将修改后的文件副本传回到原节点。
文件共享协议中的另一大类是联机访问 (on-line access)。联机访问意味着允许多个程序同时对一个文件进行存取。和数据库系统的不同之处是用户不需要调用一个特殊的客户进程,而是由操作系统提供对远地共享文件进行访问的服务,就如同对本地文件的访问一样。这就使用户可以用远地文件作为输入和输出来运行任何应用程序,而操作系统中的文件系统则提供对共享文件的透明存取。透明存取的优点是:将原来用于处理本地文件的应用程序用来处理远地文件时,不需要对该应用程序做明显的改动。属于文件共享协议的有网络文件系统 NFS (Network File System) [COME06]。网络文件系统 NFS 最初是在 UNIX 操作系统环境下实现文件和目录共享的。NFS 可使本地计算机共享远地的资源,就像这些资源在本地一样。由于 NFS 原先是美国 SUN 公司在 TCP/IP 网络上创建的,因此目前 NFS 主要应用在 TCP/IP 网络上。然而现在 NFS 也可在 OS/2, MS-Windows, NetWare 等操作系统上运行。NFS 还没有成为互联网的正式标准。经过几次修订更新,现在的最新版本(NFSv4)是 2015 年 3 月发布的建议标准 [RFC 7530]。限于篇幅,本书不讨论 NFS 的详细工作过程。
6.2.2 FTP 的基本工作原理¶
网络环境中的一项基本应用就是将文件从一台计算机中复制到另一台可能相距很远的计算机中。初看起来,在两台主机之间传送文件是很简单的事情。其实这往往非常困难。原因是众多的计算机厂商研制出的文件系统多达数百种,且差别很大。经常遇到的问题是:
(4) 访问控制方法不同。
文件传送协议 FTP 只提供文件传送的一些基本的服务,它使用 TCP 可靠的运输服务。FTP 的主要功能是减少或消除在不同操作系统下处理文件的不兼容性。
FTP 使用客户服务器方式。一个 FTP 服务器进程可同时为多个客户进程提供服务。FTP 的服务器进程由两大部分组成:一个主进程,负责接受新的请求;另外有若干个从属进程,负责处理单个请求。
主进程的工作步骤如下:
FTP 的工作情况如图 6-5 所示。图中的椭圆圈表示在系统中运行的进程。图中的服务器端有两个从属进程:控制进程和数据传送进程。为简单起见,服务器端的主进程没有画上。客户端除了控制进程和数据传送进程外,还有一个用户界面进程用来和用户接口。
在进行文件传输时,FTP 的客户和服务器之间要建立两个并行的 TCP 连接:“控制连接” 和 “数据连接”。控制连接在整个会话期间一直保持打开,FTP 客户所发出的传送请求,通过控制连接发送给服务器端的控制进程,但控制连接并不用来传送文件。实际用于传输文件的是 “数据连接”。服务器端的控制进程在接收到 FTP 客户发送来的文件传输请求后就创建 “数据传送进程” 和 “数据连接”,用来连接客户端和服务器端的数据传送进程。数据传送进程实际完成文件的传送,在传送完毕后关闭 “数据传送连接” 并结束运行。由于 FTP 使用了一个分离的控制连接,因此 FTP 的控制信息是带外 (out of band) 传送的。

当客户进程向服务器进程发出建立连接请求时,要寻找连接服务器进程的熟知端口 21,同时还要告诉服务器进程自己的另一个端口号码,用于建立数据传送连接。接着,服务器进程用自己传送数据的熟知端口 20 与客户进程所提供的端口号建立数据传送连接。由于 FTP 使用了两个不同的端口号,所以数据连接与控制连接不会发生混乱。
使用两个独立的连接的主要好处是使协议更加简单和更容易实现,同时在传输文件时还可以利用控制连接对文件的传输进行控制。例如,客户发送 “请求终止传输”。
FTP 并非对所有的数据传输都是最佳的。例如,计算机 A 上运行的应用程序要在远地计算机 B 的一个很大的文件末尾添加一行信息。若使用 FTP,则应先将此文件从计算机 B 传送到计算机 A,添加上这一行信息后,再用 FTP 将此文件传送到计算机 B,来回传送这样大的文件很花时间。实际上这种传送是不必要的,因为计算机 A 并没有使用该文件的内容。
然而网络文件系统 NFS 则采用另一种思路。NFS 允许应用进程打开一个远地文件,并能在该文件的某一个特定的位置上开始读写数据。这样,NFS 可使用户只复制一个大文件中的一个很小的片段,而不需要复制整个大文件。对于上述例子,计算机 A 中的 NFS 客户软件,把要添加的数据和在文件后面写数据的请求一起发送到远地的计算机 B 中的 NFS 服务器,NFS 服务器更新文件后返回应答信息。在网络上传送的只是少量的修改数据。
6.2.3 简单文件传送协议 TFTP¶
TCP/IP 协议族中还有一个简单文件传送协议 TFTP (Trivial File Transfer Protocol),它是一个很小且易于实现的文件传送协议 [RFC 1350, STD33]。虽然 TFTP 也使用客户服务器方式,但它使用 UDP 数据报,因此 TFTP 需要有自己的差错改正措施。TFTP 只支持文件传输而不支持交互。TFTP 没有一个庞大的命令集,没有列目录的功能,也不能对用户进行身份鉴别。
TFTP 的主要优点有两个。第一,TFTP 可用于 UDP 环境。例如,当需要将程序或文件同时向许多机器下载时就往往需要使用 TFTP。第二,TFTP 代码所占的内存较小。这对较小的计算机或某些特殊用途的设备是很重要的。这些设备不需要硬盘,只需要固化了 TFTP、UDP 和 IP 的小容量只读存储器即可。当接通电源后,设备执行只读存储器中的代码,在网络上广播一个 TFTP 请求。网络上的 TFTP 服务器就发送响应,其中包括可执行二进制程序。设备收到此文件后将其放入内存,然后开始运行程序。这种方式增加了灵活性,也减少了开销。
TFTP 的主要特点是:
TFTP 的工作很像停止等待协议(见第 5 章 5.4.1 节)。发送完一个文件块后就等待对方的确认,确认时应指明所确认的块编号。发完数据后在规定时间内收不到确认就要重发数据 PDU。发送确认 PDU 的一方若在规定时间内收不到下一个文件块,也要重发确认 PDU。这样就可保证文件的传送不致因某一个数据报的丢失而告失败。
在一开始工作时。TFTP 客户进程发送一个读请求报文或写请求报文给 TFTP 服务器进程,其熟知端口号码为 69。TFTP 服务器进程要选择一个新的端口和 TFTP 客户进程进行通信。若文件长度恰好为 512 字节的整数倍,则在文件传送完毕后,还必须在最后发送一个只含首部而无数据的数据报文。若文件长度不是 512 字节的整数倍,则最后传送数据报文中的数据字段一定不满 512 字节,这正好可作为文件结束的标志。
6.3 远程终端协议 TELNET¶
TELNET 是一个简单的远程终端协议 [RFC 854, STD8]。用户用
TELNET 就可在其所在地通过 TCP 连接注册(即登录)到远地的另一台主机上(使用主机名或 IP 地址)。TELNET 能将用户的击键传到远地主机,同时也能将远地主机的输出通过 TCP 连接返回到用户屏幕。这种服务是透明的,因为用户感觉到好像键盘和显示器是直接连在远地主机上的。因此,TELNET 又称为终端仿真协议。
TELNET 并不复杂,以前应用得很多。现在由于计算机的功能越来越强,用户已较少使用 TELNET 了,可作为历史资料了解一下即可。
TELNET 也使用客户服务器方式。在本地系统运行 TELNET 客户进程,而在远地主机则运行 TELNET 服务器进程。和 FTP 的情况相似,服务器中的主进程等待新的请求,并产生从属进程来处理每一个连接。
TELNET 能够适应许多计算机和操作系统的差异。例如,对于文本中一行的结束,有的系统使用 ASCII 码的回车 (CR),有的系统使用换行 (LF),还有的系统使用两个字符,回车 - 换行 (CR-LF)。又如,在中断一个程序时,许多系统使用 Control-C (^C),但也有系统使用 ESC 按键。为了适应这种差异,TELNET 定义了数据和命令应怎样通过互联网。这些定义就是所谓的网络虚拟终端 NVT (Network Virtual Terminal)。图 6-6 说明了 NVT 的意义。客户软件把用户的击键和命令转换成 NVT 格式,并送交服务器。服务器软件把收到的数据和命令从 NVT 格式转换成远地系统所需的格式。向用户返回数据时,服务器把远地系统的格式转换为 NVT 格式,本地客户再从 NVT 格式转换到本地系统所需的格式。

NVT 的格式定义很简单。所有的通信都使用 8 位一个字节。在运转时,NVT 使用 7 位 ASCII 码传送数据,而当高位置 1 时用作控制命令。ASCII 码共有 95 个可打印字符(如字母、数字、标点符号)和 33 个控制字符。所有可打印字符在 NVT 中的意义和在 ASCII 码中一样。但 NVT 只使用了 ASCII 码的控制字符中的几个。此外,NVT 还定义了两字符的 CR-LF 为标准的行结束控制符。当用户键入回车按键时,TELNET 的客户就把它转换为 CR-LF 再进行传输,而 TELNET 服务器要把 CR-LF 转换为远地机器的行结束字符。
TELNET 的选项协商 (Option Negotiation) 使 TELNET 客户和 TELNET 服务器可商定使用更多的终端功能,协商的双方是平等的。
6.4 万维网 WWW¶
6.4.1 万维网概述¶
万维网 WWW (World Wide Web) 是一个大规模的、联机式的信息储藏所,英文简称为 Web,而不是什么特殊的计算机网络。万维网用链接的方法能非常方便地从互联网上的一个站点访问另一个站点(也就是所谓的 “链接到另一个站点”),从而主动地按需获取丰富的信息。图 6-7 说明了万维网提供分布式服务的特点。

图 6-7 画出了四个万维网上的站点,它们可以相隔数千公里,但都必须连接在互联网上。每个万维网站点都存放了许多文档。在这些文档中有一些地方的文字是用特殊方式显示的(例如用不同的颜色,或添加了下划线),而当我们将鼠标移动到这些地方时,鼠标的箭头就变成了一只手的形状。这就表明这些地方有一个链接 (link)(这种链接有时也称为超链 hyperlink),如果我们在这些地方点击鼠标左键,就可从这个文档链接到可能相隔很远的另一个文档。经过一定的时延(几秒钟、几分钟甚至更长,取决于所链接的文档的大小和网络的拥塞情况),在我们的屏幕上就能将远方传送过来的文档显示出来。例如,站点 A 的某个文档中有两个地方有链接。点击链接①可链接到站点 B 的某个文档,点击②可链接到站点 C。站点 B 的文档也有两个链接。点击链接③可链接到站点 D,点击链接④可链接到站点 C,但站点 C 的这个文档已无其他的链接了。站点 D 的文档中有两个链接。点击⑤可链接到站点 A,点击⑥可以链接到存储在本站点硬盘中的文档。
正是由于万维网的出现,使计算机的操作发生了革命性的变化。不必在键盘上输入复杂而难以记忆的命令,而改用鼠标点击一下屏幕上的链接,这就使互联网从仅由少数计算机专家使用变为普通百姓也能利用的信息资源。万维网的出现使网站数按指数规律增长,因而成为互联网发展中的一个非常重要的里程碑。
万维网是欧洲粒子物理实验室的 Tim Berners-Lee 最初于 1989 年 3 月提出的。1993 年 2 月,第一个图形界面的浏览器 (browser) 开发成功,名字叫作 Mosaic。1995 年著名的 Netscape Navigator 浏览器上市。目前流行的浏览器很多,如微软公司的 Internet Explorer (简称 IE),谷歌公司的 Chrome 浏览器,腾讯公司的 QQ 浏览器,苹果公司的 Safari 浏览器,等等。
万维网是一个分布式的超媒体 (hypermedia) 系统,它是超文本 (hypertext) 系统的扩充。所谓超文本是指包含指向其他文档的链接的文本 (text)。也就是说,一个超文本由多个信息源链接成,而这些信息源可以分布在世界各地,并且数目也是不受限制的。利用一个链接可使用户找到远在异地的另一个文档,而这又可链接到其他的文档(依此类推)。这些文档可以位于世界上任何一个接在互联网上的超文本系统中。超文本是万维网的基础。
超媒体与超文本的区别是文档内容不同。超文本文档仅包含文本信息,而超媒体文档还包含其他表示方式的信息,如图形、图像、声音、动画以及视频图像等。
分布式的和非分布式的超媒体系统有很大区别。在非分布式系统中,各种信息都驻留在单个计算机的磁盘中。由于各种文档都可从本地获得,因此这些文档之间的链接可进行一致性检查。所以,一个非分布式超媒体系统能够保证所有的链接都是有效的和一致的。
万维网把大量信息分布在整个互联网上。每台主机上的文档都独立进行管理。对这些文档的增加、修改、删除或重新命名都不需要(实际上也不可能)通知到互联网上成千上万的节点。这样,万维网文档之间的链接就经常会不一致。例如,主机 A 上的文档 X 本来包含了一个指向主机 B 上的文档 Y 的链接。若主机 B 的管理员在某日删除了文档 Y,那么主机 A 的上述链接显然就失效了(但是 B 并没有责任必须通知 A)。
万维网以客户服务器方式工作。上面所说的浏览器就是在用户主机上的万维网客户程序。万维网文档所驻留的主机则运行服务器程序,因此这台主机也称为万维网服务器。客户程序向服务器程序发出请求,服务器程序向客户程序送回客户所要的万维网文档。在一个客户程序主窗口上显示出的万维网文档称为页面 (page)。
从以上所述可以看出,万维网必须解决以下几个问题:
为了解决第一个问题,万维网使用统一资源定位符 URL (Uniform Resource Locator) 来标志万维网上的各种文档,并使每一个文档在整个互联网的范围内具有唯一的标识符 URL。为了解决上述的第二个问题,就要使万维网客户程序与万维网服务器程序之间的交互遵守严格的协议,这就是超文本传送协议 HTTP (HyperText Transfer Protocol)。HTTP 是一个应用层协议,它使用 TCP 连接进行可靠的传送。为了解决上述的第三个问题,万维网使用超文本标记语言 HTML (HyperText Markup Language),使得万维网页面的设计者可以很方便地用链接从本页面的某处链接到互联网上的任何一个万维网页面,并且能够在自己的主机屏幕上将这些页面显示出来。最后,用户可使用搜索工具在万维网上方便地查找所需的信息。
下面我们将进一步讨论上述重要概念。
6.4.2 统一资源定位符 URL¶
1. URL 的格式¶
统一资源定位符 URL 是用来表示从互联网上得到的资源位置和访问这些资源的方法。URL 给资源的位置提供一种抽象的识别方法,并用这种方法给资源定位。只要能够对资源定位,系统就可以对资源进行各种操作,如存取、更新、替换和查找其属性。由此可见,URL 实际上就是在互联网上的资源的地址。只有知道了这个资源在互联网上的什么地方,才能对它进行操作。显然,互联网上的所有资源,都有一个唯一确定的 URL。
这里所说的 “资源” 是指在互联网上可以被访问的任何对象,包括文件目录、文件、文档、图像、声音等,以及与互联网相连的任何形式的数据。
URL 相当于一个文件名在网络范围的扩展。因此,URL 是与互联网相连的机器上的任何可访问对象的一个指针。由于访问不同对象所使用的协议不同,所以 URL 还指出读取某个对象时所使用的协议。URL 的一般形式由以下四个部分组成:
URL 最左边的协议指出使用何种协议来获取该万维网文档。现在最常用的协议就是 http(超文本传送协议 HTTP),其次是 ftp(文件传送协议 FTP)。在协议后面的 “://” 是规定的格式,必须写上。
主机名是万维网文档所存放的主机的域名,通常以 www 开头,但这并不是硬性规定。主机名用点分十进制的 IP 地址代替也是可以的。
主机名后面的 “: 端口” 就是端口号,但经常被省略掉。这是因为这个端口号通常就是协议的默认端口号(例如,协议 HTTP 的默认端口号为 80),因此就可以省略。但如不使用默认端口号,那么就必须写明现在所使用的端口号。
最后的路径可能是较长的字符串(其中还可包括若干斜线 /),但有时也不需要使用。在路径后面可能还有一些选项,这里不进行介绍了。
现在有些浏览器为了方便用户,在输入 URL 时,可以把最前面的 “http://” 甚至把主机名最前面的 “www” 省略,然后浏览器替用户把省略的字符添上。例如,用户只要键入 ctrip.com,浏览器就自动把未键入的字符补齐,变成 http://www.ctrip.com。
下面我们简单介绍使用得最多的一种 URL,即协议 HTTP。
2. 使用 HTTP 的 URL¶
使用协议 HTTP 的 URL 最常用的形式是把 “: 端口” 省略:
http:// 主机名 / 路径
若再将 URL 中的路径省略,则 URL 就指明互联网上的某个主页 (home page)。主页是个很重要的概念,它可以是以下几种情况之一:
(1) 一个 WWW 服务器的最高级别的页面。
(2) 某一个组织或部门的一个定制的页面或目录。从这样的页面可链接到互联网上的与本组织或部门有关的其他站点。
(3) 由某一个人自己设计的描述他本人情况的 WWW 页面。
例如,要查有关清华大学的信息,就可先进入到清华大学的主页,其 URL 为 \(^{①}\) :
http://www.tsinghua.edu.cn
这里省略了默认的端口号 80。我们从清华大学的主页入手,就可以通过许多不同的链接找到所要查找的各种有关清华大学各个部门的信息。
更复杂一些的路径是指向层次结构的从属页面。例如:
http://www.tsinghua.edu.cn/publish/newthu/newthu_cnt/faculties/index.html 主机域名 路径名
是清华大学的 “院系设置” 页面的 URL。注意:上面的 URL 中使用了指向文件的路径,而文件名就是最后的 index.htm。后缀 htm(有时可写为 html)表示这是一个用超文本标记语言 HTML 写出的文件。
URL 的 “协议” 和 “主机名” 部分,字母不区分大小写。但 “路径” 中的字符有时要区分大小写。
用户使用 URL 并非仅仅能够访问万维网的页面,而且还能够通过 URL 使用其他的互联网应用程序,如 FTP 或 USENET 新闻组等。更重要的是,用户在使用这些应用程序时,只使用一个程序,即浏览器。这显然是非常方便的。
6.4.3 超文本传送协议 HTTP¶
1. HTTP 的操作过程¶
协议 HTTP 定义了浏览器(即万维网客户进程)怎样向万维网服务器视频讲解 请求万维网文档,以及服务器怎样把文档传送给浏览器。从层次的角度看,HTTP 是面向事务的 (transaction-oriented) \(^{①}\) 应用层协议,它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。请注意,协议 HTTP 不仅传送完成超文本跳转所必需的信息,而且也传送任何可从互联网上得到的信息,如文本、超文本、声音和图像等。
万维网的大致工作过程如图 6-8 所示。

每个万维网网点都有一个服务器进程,它不断地监听 TCP 的端口 80,以便发现是否有浏览器(即万维网客户。请注意,浏览器和万维网客户是同义词)向它发出连接建立请求。一旦监听到连接建立请求并建立了 TCP 连接之后,浏览器就向万维网服务器发出浏览某个页面的请求,服务器接着就返回所请求的页面作为响应。服务器在完成任务后,TCP 连接就被释放了。在浏览器和服务器之间的请求和响应的交互,必须按照规定的格式和遵循一定的规则。这些格式和规则就是超文本传送协议 HTTP。
HTTP 规定在 HTTP 客户与 HTTP 服务器之间的每次交互,都由一个 ASCII 码串构成的请求和一个类似的通用互联网扩充,即 “类 MIME (MIME-like)” 的响应组成。HTTP 报文通常都使用 TCP 连接传送。
用户浏览页面的方法有两种。一种方法是在浏览器的地址窗口中键入所要找的页面的 URL。另一种方法是在某一个页面中用鼠标点击一个可选部分,这时浏览器会自动在互联网上找到所要链接的页面。
HTTP 使用了面向连接的 TCP 作为运输层协议,保证了数据的可靠传输。HTTP 不必考虑数据在传输过程中被丢弃后又怎样被重传。但是,协议 HTTP 本身是无连接的。这就是说,虽然 HTTP 使用了 TCP 连接,但通信的双方在交换 HTTP 报文之前不需要先建立 HTTP 连接。在 1997 年以前使用的是协议 HTTP/1.0 [RFC 1945]。现在普遍使用的升级版本是建议标准 HTTP/1.1 [RFC 7231]。2015 年以后,又有了新的建议标准 HTTP/2 [RFC 7540],以及压缩 HTTP 报文首部的建议标准 [RFC 7541]。
协议 HTTP 是无状态的 (stateless)。也就是说,同一个客户第二次访问同一个服务器上的页面时,服务器的响应与第一次被访问时的相同(假定现在服务器还没有把该页面更新),因为服务器并不记得曾经访问过的这个客户,也不记得为该客户曾经服务过多少次。HTTP 的无状态特性简化了服务器的设计,使服务器更容易支持大量并发的 HTTP 请求。
下面我们粗略估算一下,从浏览器请求一个万维网文档到收到整个文档所需的时间(如图 6-9 所示)。用户在点击鼠标链接某个万维网文档时,协议 HTTP 首先要和服务器建立 TCP 连接。这需要使用三报文握手。当建立 TCP 连接的三报文握手的前两个报文完成后(即经过了一个 RTT 时间后),万维网客户就把 HTTP 请求报文,作为建立 TCP 连接的三报文握手中的第三个报文的数据,发送给万维网服务器。服务器收到 HTTP 请求报文后,就把所请求的文档作为响应报文返回给客户。

从图 6-9 可看出,请求一个万维网文档所需的时间是该文档的传输时间(与文档大小成正比)加上两倍往返时间 RTT(一个 RTT 用于连接 TCP 连接,另一个 RTT 用于请求和接收万维网文档。TCP 建立连接的三报文握手的第三个报文段中的数据,就是客户对万维网文档的请求报文)。
协议 HTTP/1.0 的主要缺点,就是每请求一个文档就要有两倍 RTT 的开销。若一个主页上有很多链接的对象(如图片等)需要依次进行链接,那么每一次链接下载都导致 \(2 \times RTT\) 的开销。另一种开销就是万维网客户和服务器每一次建立新的 TCP 连接都要分配缓存和变量。特别是万维网服务器往往要同时服务于大量客户的请求,所以这种非持续连接会使万维网服务器的负担很重。好在浏览器都能够打开 5~10 个并行的 TCP 连接,而每一个 TCP 连接处理客户的一个请求。因此,使用并行 TCP 连接可以缩短响应时间。
协议 HTTP/1.1 较好地解决了这个问题,它使用了持续连接 (persistent connection)。所谓持续连接就是万维网服务器在发送响应后仍然在一段时间内保持这条连接,使同一个客户(浏览器)和该服务器可以继续在这条连接上传送后续的 HTTP 请求报文和响应报文。这并不局限于传送同一个页面上链接的文档,而是只要这些文档都在同一个服务器上就行。协议 HTTP/1.1 的持续连接有两种工作方式,即非流水线方式 (without pipelining) 和流水线方式 (with pipelining)。
非流水线方式的特点,是客户在收到前一个响应后才能发出下一个请求。因此,在 TCP 连接已建立后,客户每访问一次对象都要用去一个往返时间 RTT。这比非持续连接要用去两倍 RTT 的开销,节省了建立 TCP 连接所需的一个 RTT 时间。但非流水线方式还是有缺点的,因为服务器在发送完一个对象后,其 TCP 连接就处于空闲状态,浪费了服务器资源。
流水线方式的特点,是客户在收到 HTTP 的响应报文之前就能够接着发送新的请求报文。于是一个接一个的请求报文到达服务器后,服务器就可连续发回响应报文。因此,使用流水线方式时,客户访问所有的对象只需花费一个 RTT 时间。流水线工作方式使 TCP 连接中的空闲时间减少,提高了下载文档效率。
最初网页是以文本为主,但很快发展到使用大量的图片、音频和视频,并且对页面的实时性要求也越来越高(如视频聊天或直播),这样就使得协议 HTTP/1.1 已无法跟上互联网的发展了。于是谷歌公司在 2009 年开发了软件 SPDY,用来提高协议 HTTP/1.1 的工作效率。IETF 在此基础上与谷歌合作完成了协议 HTTP/2,而谷歌也停止了对 SPDY 的继续完善工作。
协议 HTTP/2 是协议 HTTP/1.1 的升级版本,其 HTTP 方法 / 状态码 / 语义等都没有改变,其主要特点如下:
(1) 我们知道,HTTP/1.1 具有流水线的工作方式。这就是在 TCP 连接建立后,客户可以连续向服务器发出许多个请求,而不必等到收到一个响应后再发送下一个请求。但服务器发回响应时必须按先后顺序排队,逐个地发送给客户。有时遇到某个响应迟迟不能发回,那么排在后面的一些响应就必须等待很长的时间。HTTP/2 把服务器发回的响应变成可以并行地发回(使用同一个 TCP 连接),这就大大缩短了服务器的响应时间。
(2) 使用 HTTP/1.1 时,当客户收到服务器发回的响应后,原来建立的 TCP 连接就释放了。如果客户还要继续向该服务器发送新的请求,就必须重新建立 TCP 连接。HTTP/2 允许客户复用 TCP 连接进行多个请求,这样就节省了 TCP 连续多次建立和释放连接所花费的时间。
(3) HTTP/1.1 的请求和响应报文是面向文本的 (text-oriented)。当客户连续发送请求并受到响应时,在 TCP 连接上传送的 HTTP 报文首部成为不小的开销。在这些首部中有很多字段是重复的。为此,HTTP/2 把所有的报文都划分为许多较小的二进制编码的帧,并采用了新的压缩算法,不发送重复的首部字段,大大减小了首部的开销,提高了传输效率。
因此,现在主流的浏览器都支持 HTTP/2。但是,有的服务器还未来得及更新,仍然只支持 HTTP/1.1。但 HTTP/2 是向后兼容的。当使用 HTTP/2 的客户向服务器发出请求时,如果服务器仍然使用 HTTP/1.1,那么服务器仍然可以收到请求报文。在发回响应后,客户就改用 HTTP/1.1 与服务器进行交互。
2. 代理服务器¶
代理服务器 (proxy server) 是一种网络实体,它又称为万维网高速缓存 (Web cache)。代理服务器把最近的一些请求和响应暂存在本地磁盘中。当新请求到达时,若代理服务器发现这个请求与暂时存放的请求相同,就返回暂存的响应,而不需要按 URL 的地址再次去互联网访问该资源。代理服务器可在客户端或服务器端工作,也可在中间系统上工作。下面我们用例子说明它的作用。
设图 6-10 (a) 是校园网不使用代理服务器的情况。这时,校园网中所有的计算机都通过 2 Mbit/s 专线链路( \(R_{1}-R_{2}\) )与互联网上的源点服务器建立 TCP 连接。因而校园网各计算机访问互联网的通信量往往会使这条 2 Mbit/s 的链路过载,使得时延大大增加。
图 6-10 (b) 是校园网使用代理服务器的情况。这时,访问互联网的过程是这样的:


给请求该对象的浏览器。
我们注意到,代理服务器有时是作为服务器(当接受浏览器的 HTTP 请求时),但有时却作为客户(当向互联网上的源点服务器发送 HTTP 请求时)。
在使用代理服务器的情况下,由于有相当大一部分通信量局限在校园网的内部,因此,2 Mbit/s 专线链路( \(R_{1}-R_{2}\) )上的通信量大大减少,因而减小了访问互联网的时延。
以代理服务器方式构成的内容分发网络 CDN (Content Distribution Network) 在互联网应用中起到了很大的作用。最先使用 CDN 技术的是美国的 Akamai (阿卡迈) 公司。Akamai 公司现在是全球最大的 CDN 平台,是全球能够提供最大规模分发在线视频的服务商。目前 Akamai 公司拥有 24 万台服务器,3900 个位置节点,使全球的用户可以就近下载视频、音频节目,或进行其他业务联系,而用户甚至根本不知道已经使用了 Akamai 提供的服务。现在 Akamai 与全球多家电信运营商建立了深度合作关系,所提供的通信流量高达每秒 40 TB,业务遍及 137 个国家和地区。
3. HTTP 的报文结构¶
HTTP 有两类报文:


由于 HTTP 是面向文本的,因此在报文中的每一个字段都是一些 ASCII 码串,因而各个字段的长度都是不确定的。
HTTP 请求报文和响应报文都是由三个部分组成的。可以看出,这两种报文格式的区别就是开始行不同。
下面先介绍 HTTP 请求报文的一些主要特点。
请求报文的第一行 “请求行” 只有三个内容,即方法、请求资源的 URL,以及 HTTP 的版本。
请注意:这里的名词 “方法” (method) 是面向对象技术中使用的专门名词。所谓 “方法” 就是对所请求的对象进行的操作,这些方法实际上也就是一些命令。因此,请求报文的类型是由它所采用的方法决定的。表 6-1 给出了请求报文中常用的几种方法。
表 6-1 HTTP 请求报文的一些方法
| 方法(操作) | 意义 |
| OPTION | 请求一些选项的信息 |
| GET | 请求读取由URL所标志的信息 |
| HEAD | 请求读取由URL所标志的信息的首部 |
| POST | 给服务器添加信息(例如,注释) |
| PUT | 在指明的URL下存储一个文档 |
| DELETE | 删除指明的URL所标志的资源 |
| TRACE | 用来进行环回测试的请求报文 |
| CONNECT | 用于代理服务器 |
下面是 HTTP 的请求报文的开始行(即请求行)的格式。请注意,在 GET 后面有一个空格,接着是某个完整的 URL,其后面又有一个空格,最后是 HTTP/1.1。
GET http://www.xyz.edu.cn/dir/index.htm HTTP/1.1
下面是一个完整的 HTTP 请求报文的例子:
GET /dir/index.htm HTTP/1.1
{请求行使用了相对 URL}
Host: www.xyz.edu.cn
{此行是首部行的开始。这行给出主机的域名}
Connection: close
{告诉服务器发送完请求的文档后就可释放连接}
User-Agent: Mozilla/5.0
{表明用户代理是使用火狐浏览器 Firefox}
Accept-Language: cn
{表示用户希望优先得到中文版本的文档}
{请求报文的最后还有一个空行}
在请求行使用了相对 URL(即省略了主机的域名)是因为下面的首部行(第 2 行)给出了主机的域名。第 3 行是告诉服务器不使用持续连接,表示浏览器希望服务器在传送完所请求的对象后即关闭 TCP 连接。这个请求报文没有实体主体。
再看一下 HTTP 响应报文的主要特点。
每一个请求报文发出后,都能收到一个响应报文。响应报文的第一行就是状态行。
状态行包括三项内容,即 HTTP 的版本、状态码,以及解释状态码的简单短语。
状态码 (Status-Code) 都是三位数字的,分为 5 大类,原先有 33 种 [RFC 2616],后来又增加了几种 [RFC 6585,建议标准]。这 5 大类的状态码都是以不同的数字开头的。
1xx 表示通知信息,如请求收到了或正在进行处理。
2xx 表示成功,如接受或知道了。
3xx 表示重定向,如要完成请求还必须采取进一步的行动。
4xx 表示客户的差错,如请求中有错误的语法或不能完成。
5xx 表示服务器的差错,如服务器失效无法完成请求。
下面三种状态行在响应报文中是经常见到的。
若请求的网页从 http://www.ee.xyz.edu/index.html 转移到了一个新的地址,则响应报文的状态行和一个首部行就是下面的形式:
HTTP/1.1 301 Moved Permanently {永久性地转移了}
Location: http://www.xyz.edu/ee/index.html {新的 URL}
4. 在服务器上存放用户的信息¶
在本节(6.4.3 节)第 1 小节 “HTTP 的操作过程” 中已经讲过,HTTP 是无状态的。这样做虽然简化了服务器的设计,但在实际工作中,一些万维网站点却常常希望能够识别用户。例如,在网上购物时,一个顾客要购买多种物品。当他把选好的一件物品放入 “购物车” 后,他还要继续浏览和选购其他物品。因此,服务器需要记住用户的身份,使他接着选购的一些物品能够放入同一个 “购物车” 中,这样就便于集中结账。有时某些万维网站点也可能想限制某些用户的访问。要做到这点,可以在 HTTP 中使用 Cookie。在 RFC 6265 中对 Cookie 进行了定义,规定万维网站点可以使用 Cookie 来跟踪用户。Cookie 原意是 “小甜饼”(广东人用方言音译为 “曲奇”),目前尚无标准译名,在这里 Cookie 表示在 HTTP 服务器和客户之间传递的状态信息。现在很多网站都已广泛使用 Cookie。
Cookie 是这样工作的:当用户 A 浏览某个使用 Cookie 的网站时,该网站的服务器就为 A 产生一个唯一的识别码,并以此作为索引在服务器的后端数据库中产生一个项目。接着在给 A 的 HTTP 响应报文中添加一个叫作 Set-cookie 的首部行。这里的 “首部字段名” 就是 “Set-cookie”,而后面的 “值” 就是赋予该用户的 “识别码”。例如这个首部行是这样的:
Set-cookie: 31d4d96e407aad42
当 A 收到这个响应时,其浏览器就在它管理的特定 Cookie 文件中添加一行,其中包括这个服务器的主机名和 Set-cookie 后面给出的识别码。当 A 继续浏览这个网站时,每发送一个 HTTP 请求报文,其浏览器就会从其 Cookie 文件中取出这个网站的识别码,并放到 HTTP 请求报文的 Cookie 首部行中:
Cookie: 31d4d96e407aad42
于是,这个网站就能够跟踪用户 31d4d96e407aad42(用户 A)在该网站的活动。需要注意的是,服务器并不需要知道这个用户的真实姓名以及其他的信息。但服务器能够知道用户 31d4d96e407aad42 在什么时间访问了哪些页面,以及访问这些页面的顺序。如果 A 是在网上购物,那么这个服务器可以为 A 维护一个所购物品的列表,使 A 在结束这次购物时可以一起付费。
如果 A 在几天后再次访问这个网站,那么他的浏览器会在其 HTTP 请求报文中继续使用首部行 Cookie: 31d4d96e407aad42,而这个网站服务器根据 A 过去的访问记录可以向他推荐商品。如果 A 已经在该网站登记过和使用过信用卡付费,那么这个网站就已经保存了 A 的姓名、电子邮件地址、信用卡号码等信息。这样,当 A 继续在该网站购物时,只要还使用同一个计算机上网,由于浏览器产生的 HTTP 请求报文中都携带了同样的 Cookie 首部行,服务器就可利用 Cookie 来验证出这是用户 A,因此以后 A 在这个网站购物时就不必重新在键盘上输入姓名、信用卡号码等信息。这对顾客显然是很方便的。
尽管 Cookie 能够简化用户网上购物的过程,但 Cookie 的使用一直引起很多争议。有人认为 Cookie 会把计算机病毒带到用户的计算机中。其实这是对 Cookie 的误解。Cookie 只是一个小小的文本文件,不是计算机的可执行程序,因此不可能传播计算机病毒,也不可能用来获取用户计算机硬盘中的信息。对于 Cookie 的另一个争议,是关于用户隐私的保护问题。例如,网站服务器知道了 A 的一些信息,就有可能把这些信息出卖给第三方。Cookie 还可用来收集用户在万维网网站上的行为。这些都属于用户个人的隐私。有些网站为了使顾客放心,就公开声明他们会保护顾客的隐私,绝对不会把顾客的识别码或个人信息出售或转移给其他厂商。
为了让用户有拒绝接受 Cookie 的自由,在浏览器中用户可自行设置接受 Cookie 的条件。例如在浏览器 IE 11.0 中,选择工具栏中的 “工具” → “Internet 选项” → “隐私” 命令,就可以看见菜单中的左边有一个可上下滑动的标尺,它有六个位置。最高的位置是阻止所有 Cookie,而最低的位置是接受所有 Cookie。中间的位置则是在不同条件下可以接受 Cookie。用户可根据自己的情况对 IE 浏览器进行必要的设置。
6.4.4 万维网的文档¶
1. 超文本标记语言 HTML¶
要使任何一台计算机都能显示出任何一个万维网服务器上的页面,就必须解决页面制作的标准化问题。超文本标记语言 HTML (HyperText Markup Language) 就是一种制作万维网页面的标准语言,它消除了不同计算机之间信息交流的障碍。但请注意,HTML 并不是应用层的协议,它只是万维网浏览器使用的一种语言。由于 HTML 非常易于掌握且实施简单,因此它很快就成为万维网的重要基础 [RFC 2854]。官方的 HTML 标准由万维网联盟 W3C(即 WWW Consortium)负责制定。有关 HTML 的一些参考资料见 [W-HTML]。从 HTML 在 1993 年问世后,就不断地对其版本进行更新。现在最新的版本是 HTML 5.0,新的版本增加了
HTML 定义了许多用于排版的命令,即 “标签” (tag) \(^{①}\) 。例如, 表示后面开始用斜体字排版,而 则表示斜体字排版到此结束。HTML 把各种标签嵌入到万维网的页面中,这样就构成了所谓的 HTML 文档。HTML 文档是一种可以用任何文本编辑器(例如,Windows 的记事本 Notepad)创建的 ASCII 码文件。但应注意,仅当 HTML 文档是以.html 或 .htm 为后缀时,浏览器才对这样的 HTML 文档的各种标签进行解释。如果 HTML 文档改为以 .txt 为其后缀,则 HTML 解释程序就不对标签进行解释,而浏览器只能看见原来的文本文件。
并非所有的浏览器都支持所有的 HTML 标签。若某一个浏览器不支持某一个 HTML 标签,则浏览器将忽略此标签,但在一对不能识别的标签之间的文本仍然会被显示出来。
下面是一个简单例子,用来说明 HTML 文档中标签的用法。在每一个语句后面的花括号中的字是给读者看的注释,在实际的 HTML 文档中并没有这种注释。
把上面的 HTML 文档存入 D 盘的文件夹 HTML 中,文件名是 HTML-example.html(注意:实际的文档中没有注释部分)。当浏览器读取了该文档后,就按照 HTML 文档中的各种标签,根据浏览器所使用的显示器的尺寸和分辨率大小,重新进行排版并显示出来。图 6-12 表示 IE 浏览器在计算机屏幕上显示出的与该文档有关部分的画面。文档的标题 (title)“一个 HTML 的例子” 显示在浏览器最上面的标题栏中。文件的路径显示在地址栏中。再下面就是文档的主体部分。主体部分的题头 (heading),即文档主体部分的标题 “HTML 很容易掌握”,用较大的字号显示出来,因为在标签中指明了使用的是 1 级题头
。
目前已开发出了很好的制作万维网页面的软件工具,使我们能够像使用 Word 文字处理器那样很方便地制作各种页面。即使我们用 Word 文字处理器编辑了一个文件,但只要在 “另存为 (Save As)” 时选取文件后缀为.htm 或.html,就可以很方便地把 Word 的.doc 格式文件转换为浏览器可以显示的 HTML 格式的文档。

HTML 允许在万维网页面中插入图像。一个页面本身带有的图像称为内含图像 (inline image)。HTML 标准并没有规定该图像的格式。实际上,大多数浏览器都支持 GIF 和 JPEG 文件。很多格式的图像占据的存储空间太大,因而这种图像在互联网传送时就很浪费时间。例如,一幅位图文件 (.bmp) 可能要占用 500 \~ 700 KB 的存储空间。但若将此图像改存为经压缩的 .gif 格式,则可能只有十几个千字节,大大减少了存储空间。
HTML 还规定了链接的设置方法。我们知道每个链接都有一个起点和终点。链接的起点说明在万维网页面中的什么地方可引出一个链接。在一个页面中,链接的起点可以是一个字或几个字,或是一幅图,或是一段文字。在浏览器所显示的页面上,链接的起点是很容易识别的。在以文字作为链接的起点时,这些文字往往用不同的颜色显示(例如,一般的文字用黑色字时,链接起点往往使用蓝色字),甚至还会加上下划线(一般由浏览器来设置)。当我们将鼠标移动到一个链接的起点时,表示鼠标位置的箭头就变成了一只手。这时只要点击鼠标,这个链接就被激活。
链接的终点可以是其他网站上的页面。这种链接方式叫作远程链接。这时必须在 HTML 文档中指明链接到的网站的 URL。有时链接可以指向本计算机中的某一个文件或本文件中的某处,这叫作本地链接。这时必须在 HTML 文档中指明链接的路径。
实际上,现在这种链接方式已经不局限于用在万维网文档中。在最常用的 Word 文字处理器的工具栏中,也设有 “插入超链接” 的按钮。只要点击这个按钮,就可以看到设置超链接的窗口。用户可以很方便地在自己写的 Word 文档中设置各种链接的起点和终点。
在这一小节的最后,我们还要简单介绍一下和浏览器有关的几种其他语言。
XML (Extensible Markup Language) 是可扩展标记语言,它和 HTML 很相似。但 XML 的设计宗旨是传输数据,而不是显示数据(HTML 是为了在浏览器上显示数据)。更具体些,XML 用于标记电子文件,使其具有结构性的标记语言,可用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML 是一种简单、与平台无关并被广泛采用的标准。XML 相对于 HTML 的优点是它将用户界面与结构化数据分隔开来。这种数据与显示的分离使得集成来自不同源的数据成为可能。客户信息、订单、研究结果、账单付款、病历、目录数据及其他信息都可以转换为 XML。XML 不是要替换 HTML,而是对 HTML 的补充。XML 标记由文档的作者定义,并且是无限制的。HTML 标记则是预定义的;HTML 作者只能使用当前 HTML 标准所支持的标记。
另一种语言 XHTML (Extensible HTML) 是可扩展超文本标记语言,它与 HTML 4.01 几乎是相同的。但 XHTML 是更严格的 HTML 版本,也是一个 W3C 标准(2000 年 1 月制定),是作为一种 XML 应用被重新定义的 HTML,并将逐渐取代 HTML。所有新的浏览器都支持 XHTML。
还有一种语言 CSS (Cascading Style Sheets) 是层叠样式表,它是一种样式表语言,用于为 HTML 文档定义布局。CSS 与 HTML 的区别就是:HTML 用于结构化内容,而 CSS 则用于格式化结构化的内容。例如,在浏览器上显示的字体、颜色、边距、高度、宽度、背景图像等方面,都能够给出精确的规定。现在所有的浏览器都支持 CSS。
2. 动态万维网文档¶
上面所讨论的万维网文档只是万维网文档中最基本的一种,即所谓的静态文档 (static document)。静态文档在文档创作完毕后就存放在万维网服务器中,在被用户浏览的过程中,内容不会改变。由于这种文档的内容不会改变,因此用户对静态文档的每次读取所得到的返回结果都是相同的。
静态文档的最大优点是简单。由于 HTML 是一种排版语言,因此静态文档可以由不懂程序设计的人员来创建。但静态文档的缺点是不够灵活。当信息变化时就要由文档的作者手工对文档进行修改。可见,变化频繁的文档不适于做成静态文档。
动态文档 (dynamic document) 是指文档的内容是在浏览器访问万维网服务器时才由应用程序动态创建的。当浏览器请求到达时,万维网服务器要运行另一个应用程序,并把控制转移到此应用程序。接着,该应用程序对浏览器发来的数据进行处理,并输出 HTML 格式的文档,万维网服务器把应用程序的输出作为对浏览器的响应。由于对浏览器每次请求的响应都是临时生成的,因此用户通过动态文档所看到的内容是不断变化的。动态文档的主要优点是具有报告当前最新信息的能力。例如,动态文档可用来报告股市行情、天气预报或民航售票情况等内容。但动态文档的创建难度比静态文档的高,因为动态文档的开发不是直接编写文档本身,而是编写用于生成文档的应用程序,这就要求动态文档的开发人员必须会编程,而所编写的程序还要通过大范围的测试,以保证输入的有效性。
动态文档和静态文档之间的主要差别体现在服务器一端。这主要是文档内容的生成方法不同。而从浏览器的角度看,这两种文档并没有区别。动态文档和静态文档的内容都遵循 HTML 所规定的格式,浏览器仅根据在屏幕上看到的内容无法判定服务器送来的是哪一种文档,只有文档的开发者才知道。
从以上所述可以看出,要实现动态文档就必须在以下两个方面对万维网服务器的功能进行扩充:
(1) 应增加另一个应用程序,用来处理浏览器发来的数据,并创建动态文档。
(2) 应增加一个机制,用来使万维网服务器将浏览器发来的数据传送给这个应用程序,然后万维网服务器能够解释这个应用程序的输出,并向浏览器返回 HTML 文档。
图 6-13 是扩充了功能的万维网服务器的示意图。这里增加了一个机制,叫作通用网关接口 CGI (Common Gateway Interface)。CGI 是一种标准,它定义了动态文档应如何创建,输入数据应如何提供给应用程序,以及输出结果应如何使用。
在万维网服务器中新增加的应用程序叫作 CGI 程序。取这个名字的原因是:万维网服务器与 CGI 的通信遵循 CGI 标准。“通用” 是因为这个标准所定义的规则对其他任何语言都是通用的。“网关” 二字的出现是因为 CGI 程序还可能访问其他的服务器资源,如数据库或图形软件包,因而 CGI 程序的作用有点像一个网关。也有人将 CGI 程序简称为网关程序。“接口” 是因为有一些已定义好的变量和调用等可供其他 CGI 程序使用。请读者注意:在看到 CGI 这个名词时,应弄清是指 CGI 标准,还是指 CGI 程序。

CGI 程序的正式名字是 CGI 脚本 (script)。按照计算机科学的一般概念,“脚本” \(^{①}\) 指的是一个程序,它被另一个程序(解释程序)而不是计算机的处理机来解释或执行。有一些语言专门作为脚本语言 (script language),如 Perl, REXX(在 IBM 主机上使用),JavaScript 以及 Tcl/Tk 等。脚本也可用一些常用的编程语言写出,如 C, C++ 等。使用脚本语言可更容易和更快地进行编码,这对一些有限功能的小程序是很合适的。但一个脚本运行起来比一般的编译程序要慢,因为它的每一条指令先要被另一个程序来处理(这就要一些附加的指令),而不是直接被指令处理器来处理。脚本不一定是一个独立的程序,它可以是一个动态装入的库,甚至是服务器的一个子程序。
CGI 程序又称为 cgi-bin 脚本,这是因为在许多万维网服务器上,为便于找到 CGI 程序,就将 CGI 程序放在 /cgi-bin 的目录下。
3. 活动万维网文档¶
随着 HTTP 和万维网浏览器的发展,上一节所述的动态文档已明显地不能满足发展的需要。这是因为,动态文档一旦建立,它所包含的信息内容也就固定下来而无法及时刷新屏幕。另外,像动画之类的显示效果,动态文档也无法提供。
有两种技术可用于浏览器屏幕显示的连续更新。一种技术称为服务器推送 (server push),这种技术是将所有的工作都交给服务器。服务器不断地运行与动态文档相关联的应用程序,定期更新信息,并发送更新过的文档。
尽管从用户的角度看,这样做可达到连续更新的目的,但这也有很大的缺点。首先,为了满足很多客户的请求,服务器就要运行很多服务器推送程序。这将造成过多的服务器开销。其次,服务器推送技术要求服务器为每一个浏览器客户维持一个不释放的 TCP 连接。随着 TCP 连接的数目增加,每一个连接所能分配到的网络带宽就下降,这就导致网络传输时延的增大。
另一种提供屏幕连续更新的技术是活动文档 (active document)。这种技术是把所有的工作都转移给浏览器端。每当浏览器请求一个活动文档时,服务器就返回一段活动文档程序副本,使该程序副本在浏览器端运行。这时,活动文档程序可与用户直接交互,并可连续地改变屏幕的显示。只要用户运行活动文档程序,活动文档的内容就可以连续地改变。由于活动文档技术不需要服务器的连续更新传送,对网络带宽的要求也不会太高。
从传送的角度看,浏览器和服务器都把活动文档看成是静态文档。在服务器上的活动文档的内容是不变的,这点和动态文档是不同的。浏览器可在本地缓存一份活动文档的副本。活动文档还可处理成压缩形式,以便于存储和传送。另一点要注意的是,活动文档本身并不包括其运行所需的全部软件,大部分的支持软件是事先存放在浏览器中的。图 6-14 说明了活动文档的创建过程。
由美国 SUN 公司开发的 Java 语言是一项用于创建和运行活动文档的技术。在 Java 技术中使用了一个新的名词 “小应用程序” (applet) \(^{①}\) 来描述活动文档程序。当用户从万维网服务器下载一个嵌入了 Java 小应用程序的 HTML 文档后,用户可在浏览器的显示屏幕上点击某个图像,然后就可看到动画的效果;或是在某个下拉式菜单中点击某个项目,即可看到根据用户键入的数据所得到的计算结果。实际上,Java 技术是活动文档技术的一部分。限于篇幅,有关 Java 技术的进一步讨论这里从略。

6.4.5 万维网的信息检索系统¶
1. 全文检索搜索与分类目录搜索¶
万维网是一个大规模的、联机式的信息储藏所。那么,应当采用什么方法才能找到所需的信息呢?如果已经知道存放该信息的网点,那么只要在浏览器的地址 (Location) 框内键入该网点的 URL 并按回车键,就可进入该网点。但是,若不知道要找的信息在何网点,那就要使用万维网的搜索工具。
在万维网中用来进行搜索的工具叫作搜索引擎 (search engine)。搜索引擎的种类很多,但大体上可划分为两大类,即全文检索搜索引擎和分类目录搜索引擎。
全文检索搜索引擎是一种纯技术型的检索工具。它的工作原理是通过搜索软件(例如一种叫作 “蜘蛛” 或 “网络机器人” 的 Spider 程序)到互联网上的各网站收集信息,找到一个网站后可以从这个网站再链接到另一个网站,像蜘蛛爬行一样。然后按照一定的规则建立一个很大的在线索引数据库供用户查询。用户在查询时只要输入关键词,就从已经建立的索引数据库里进行查询(并不是实时地在互联网上检索到的信息)。因此很可能有些查到的信息已经是过时的(例如很多年前的)。建立这种索引数据库的网站必须定期对已建立的数据库进行更新维护(但不少网站的维护很不及时,因此对查找到的信息一定要注意其发布的时间)。现在全球最大的并且最受欢迎的全文检索搜索引擎就是谷歌 Google (www.google.com)。谷歌提供的主要的搜索服务有:网页搜索、图片搜索、视频搜索、地图搜索、新闻搜索、购物搜索、博客搜索、论坛搜索、学术搜索、财经搜索等。应全球用户的需求,谷歌在美国及世界各地创建数据中心。至 2013 年底,谷歌的数据中心在全球共设有 12 处。大多数数据中心的业主基于信息安全考虑,极少透露其数据中心的信息及内部情形。
我们将在下一小节简单介绍谷歌搜索技术的特点。现在 “谷歌” 不仅是网站名,而且还是动词。例如,“谷歌一下” 的意思就是 “用谷歌网站进行信息搜索”。在全文检索搜索引擎中另外两个著名的网站是美国微软的必应 (cn.bing.com) 和中国的百度 (www.baidu.com)。
分类目录搜索引擎并不采集网站的任何信息,而是利用各网站向搜索引擎提交网站信息时填写的关键词和网站描述等信息,经过人工审核编辑后,如果认为符合网站登录的条件,则输入到分类目录的数据库中,供网上用户查询。因此,分类目录搜索也叫作分类网站搜索。分类目录的好处就是用户可根据网站设计好的目录有针对性地逐级查询所需要的信息,查询时不需要使用关键词,只需要按照分类(先找大类,再找下面的小类),因而查询的准确性较好。但分类目录查询的结果并不是具体的页面,而是被收录网站主页的 URL 地址,因而所得到的内容就比较有限。相比之下,全文检索可以检索出大量的信息(一次检索的结果是几百万条,甚至是千万条以上),但缺点是查询结果不够准确,往往是罗列出了海量的信息(如上千万个页面),使用户无法迅速找到所需的信息。在分类目录搜索引擎中最著名的就是雅虎 (www.yahoo.com)。国内著名的分类搜索引擎有雅虎中国 (cn.yahoo.com)、新浪 (sina.com.cn)、搜狐 (www.sohu.com)、网易 (www.163.com) 等。
图 6-16 说明了上述这两种搜索方法的区别。图 6-15 (a) 是全文搜索谷歌的首页。用户只需在空白的栏目中键入拟搜索的关键词,搜索引擎就返回搜索结果,用户可根据屏幕上显示的结果继续点击下去,直到看到满意的结果。图 6-15 (b) 是分类检索新浪网的首页。我们可以看到页面上有三行共 63 个类别。用户要检索的内容通常总是在这几十个类别之中,因此按类别点击查找下去,最后就可以查找到所要检索的内容。


从用户的角度看,使用这两种不同的搜索引擎一般都能够实现自己查询信息的目的。为了使用户能够更加方便地搜索到有用信息,目前许多网站往往同时具有全文检索搜索和分类目录搜索的功能。在互联网上搜索信息需要经验的积累。要多实践才能掌握从互联网获取信息的技巧。
这里再强调一下,不管哪种搜索引擎,就是告诉你只要链接到什么地方就可以检索到所需的信息。搜索引擎网站本身并没有直接存储这些信息。
值得注意的是,目前出现了垂直搜索引擎 (vertical search engine),它针对某一特定领域、特定人群或某一特定需求提供搜索服务。垂直搜索也是提供关键字来进行搜索的,但被放到了一个行业知识的上下文中,返回的结果更倾向于信息、消息、条目等。例如,对买房的人讲,他希望查找的是房子的具体供求信息(如面积、地点、价格等),而不是有关房子供求的一般性的论文或新闻、政策等。目前热门的垂直搜索行业有:购物、旅游、汽车、求职、房产、交友等。还有一种元搜索引擎 (meta search engine),它把用户提交的检索请求发送到多个独立的搜索引擎上去搜索,并把检索结果集中统一处理,以统一的格式提供给用户,因此是搜索引擎之上的搜索引擎。它的主要精力放在提高搜索速度、智能化处理搜索结果、个性化搜索功能的设置和用户检索界面的友好性上。元搜索引擎的查全率和查准率都比较高。
2. Google 搜索技术的特点¶
Google 的搜索引擎性能优良,因为它使用了先进的硬件和软件。以往的大多数的搜索引擎是使用少量大型服务器,在访问高峰期,搜索的速度就会明显减慢。Google 则利用在互联网上相互链接的计算机来快速查找每个搜索的答案,并且成功地缩短了查找的相应时间。Google 的搜索软件可同时进行许多运算,它的核心技术就是 PageRank \(^{TM}\) ,译为网页排名。
PageRank 对搜索出来的结果按重要性进行排序,这是 Google 的两个创始人 Larry Page 和 Sergey Brin 共同开发出来的 [W-PageRank]。由于用户在有限的时间内,不可能阅读全部的搜索结果(因为数量往往非常大),而通常仅仅是查阅一下前几个(或前几十个)项目。因此用户希望检索结果能够按重要性来排序。但怎样确定某个页面的重要性呢?传统的搜索引擎往往是检查关键字在网页上出现的频率。PageRank 技术则把整个互联网当作了一个整体对待,检查整个网络链接的结构,并确定哪些网页重要性最高。更具体些,就是如果有很多网站上的链接都指向页面 A,那么页面 A 就比较重要。PageRank 对链接的数目进行加权统计。对来自重要网站的链接,其权重也较大。统计链接数目的问题是一个二维矩阵相乘的问题,从理论上讲,这种二维矩阵的元素数是网页数目的平方。对于 1 亿个网页,这个矩阵就有 1 亿亿个元素。这样大的矩阵相乘,计算量是非常大的。Larry Page 和 Sergey Brin 两人利用稀疏矩阵计算的技巧,大大地简化了计算量。他们用迭代的方法解决了这个问题。他们先假定所有网页的排名是相同的,并且根据此初始值,算出各个网页的第一次迭代排名,再根据第一次迭代排名算出第二次的排名。他们从理论上证明了不论初始值如何选取,这种算法都保证了网页排名的估计值能收敛到排名的真实值。这种算法是完全没有任何人工干预的,厂商不可能用金钱购买网页的排名。Google 还要进行超文本匹配分析,以确定哪些网页与正在执行的特定搜索相关。在综合考虑整体重要性以及与特定查询的相关性之后,Google 就把最相关、最可靠的搜索结果放在首位。
然而有一些著名网站通过 “竞价排名” 把虚假广告信息放在检索结果的首位,结果误导了消费者,使受骗者蒙受很大的损失。因此对网络搜索的结果,我们应认真分析其真伪,提高辨别能力,不要随意轻信网络检索的广告信息(哪怕是知名度很高的网站)。
6.4.6 博客和微博¶
近年来,万维网的一些新的应用广为流行,这就是博客和微博。下面进行简单的介绍。
1. 博客¶
我们知道,建立网站就是万维网的一种应用。博客 (blog) 和网站有很相似的地方。博客的作者可以源源不断地往万维网上的个人博客里填充内容,供其他网民阅读。网民可以用浏览器上网阅读博客、发表评论,也可以什么都不做。
博客是万维网日志 (weblog) 的简称。也有人把 blog 进行音译,译为 “部落格”,或 “部落阁”。还有人用 “博文” 来表示 “博客文章”。
本来,网络日志是指个人撰写并在互联网上发布的、属于网络共享的个人日记。但现在它不仅可以是个人日记,而且可以有无数的形式和大小,也没有任何实际的规则。
现在博客已经极大地扩充了互联网的应用和影响,成为了所有网民都可以参与的一种新媒体,并使得无数的网民有了发言权,有了与政府、机构、企业,以及很多人交流的机会。在博客出现以前,网民是互联网上内容的消费者,网民在互联网上搜寻并下载感兴趣的信息。这些信息是其他人生产的,他们把这些信息放在互联网的某个服务器上,供广大网民使用(也就是供网民消费)。但博客改变了这种情况,网民不仅是互联网上内容的消费者,而且还是互联网上内容的生产者。
从历史上看,weblog 这个新词是 Jorn Barger 于 1997 年创造的。简写的 blog(这是今天最常用的术语)则是 Peter Merholz 于 1999 年创造的。不久,有人把 blog 既当作名词,也当作动词,表示编辑博客或写博客。接着,新名词 blogger 也出现了,它表示博客的拥有者,或博客内容的撰写者和维护者,或博客用户。博客可以看成是继电子邮件、电子公告牌系统 BBS 和即时传信 IM (Instant Messaging) \(^{①}\) 之后的第四种网络交流方式。
现在从一些著名的门户网站的主页上都能很容易地进入到博客页面,这让用户查看博客或发表自己的博客都非常方便。前面的图 6-15 (b) 所示的新浪网站首页,就可看到在几十个分类中的第 1 行第 9 列的 “博客”。
当我们在新浪网站主页点击 “博客” 项时,就可以看到各式各样的博客。也可以利用搜索工具寻找所需的博客。如果我们已在新浪博客注册了,那么也可随时把自己的博客发表在此,让别人来阅读。我们还可直接登录新浪博客网站 blog.sina.com.cn。
博客与个人网站还是有不少区别的。这里最主要的区别就是建立个人网站成本较高,需要租用个人空间、域名等,同时建立网站的个人需要懂得 HTML 语言和网页制作等相关技术;但博客在这方面是不需要什么投资的,所需的技术仅仅是会上网和会用键盘或书写板输入汉字即可。因此网民用较短的时间就能够把自己写的博客发表在网上,而不像制作个人网站那样花费较多的时间。正因为写博客的门槛较低,广大的网民才有可能成为今天互联网上的信息制造者。
顺便提一下,不要把 “博客” 和 “播客” 弄混。播客 (Podcast) 是苹果手机的一个预装软件,能够让用户通过手机订阅和自动下载所预订的音乐文件,以便随时欣赏音乐。
2. 微博¶
在图 6-15 (b) 新浪网站首页各种分类的第 1 行的最后,可以找到 “微博” 项。微博就是微型博客 (microblog),又称为微博客,它的意思已经非常清楚。博客或微博里的朋友,常称为 “博友”。微博也被人戏称为 “围脖”,把博友戏称为 “脖友”。
但微博不同于一般的博客。微博只记录片段、碎语,三言两语,现场记录,发发感慨,晒晒心情,永远只针对一个问题进行回答。微博只是记录自己琐碎的生活,呈现给人看,而且必须很真实。微博中不必有太多的逻辑思维,很随便,很自由,有点像电影中的一个镜头。写微博比写其他东西简单多了,不需要标题,不需要段落,更不需要漂亮的词汇。
2009 年是中国微博蓬勃发展的一年,相继出现了新浪微博、139 说客、9911、嘀咕网、同学网、贫嘴等微博客。例如,新浪微博就是由中国最大的门户网站新浪网推出的微博服务,是中国目前用户数最多的微博网站 (weibo.com),名人用户众多是新浪微博的一大特色,基本已经覆盖大部分知名文体明星、企业高管、媒体人士。用户可以通过网页、WAP 网、手机短信彩信、手机客户端等多种方式更新自己的微博。每条微博字数最初限制为 140 英文字符,但现在已增加了 “长微博” 的选项,可输入更多的字符。微博还提供插入图片、视频、音乐等功能。截至 2019 年 3 月底,微博的月活跃用户已达 4.65 亿。
现在不少地方政府也开通了微博(即政务微博),这是信息公开的表现。政府可以通过政务微博,及时公布政情、公务、资讯等,获取与民众更多、更直接、更快的沟通,特别是在突发事件或者群体性事件发生的时候,微博就能够成为政府新闻发布的一种重要手段。
虽然政务微博具有 “传递信息、沟通上下、解决问题” 的功能性特点,并受到广大网民的欢迎,但政务微博的日常管理也非常重要。如果政务微博因缺乏良好的管理而不能够满足群众的各种需求,那么它就会成为一种无用的摆设。
微博是一种互动及传播性极快的工具,其实时性、现场感及快捷性,往往超过所有媒体。这是因为微博对用户的技术要求门槛非常低,而且在语言的编排组织上,没有博客那么高。另外,微博开通的多种 API 使大量的用户可通过手机、网络等方式来即时更新自己的个人信息。微博网站的即时传信功能非常强大,可以通过 QQ 和 MSN 直接书写。
我们正处在一个急剧变革的时代,人们需要用贯穿不同社会阶层的信息去了解社会、改变生活。在互联网上微博的出现正好满足了广大网民的需求。微博发布、转发信息的功能很强大,这种一个人的 “通讯社” 将对整个社会产生越来越大的影响。
6.4.7 社交网站¶
社交网站 SNS (Social Networking Site) 是近年来发展非常迅速的一种网站,其作用是为一群拥有相同兴趣与活动的人创建在线社区。社交网站的功能非常丰富,如电子邮件、即时传信(在线聊天)、博客撰写、共享相册、上传视频、网页游戏、创建社团、刊登广告等,对现实社交结构已经形成了巨大冲击。社交网络服务提供商针对不同的群众,有着不同的定位,对个人消费者都是免费的。这种网站通过朋友,一传十、十传百地把联系范围不断扩大下去。前面曾提到过的 BBS 和微博,可以看作是社交网站的前身。
2004 年社交网站脸书(Facebook,又名面书、脸谱、脸谱网)在美国诞生。脸书最初的用户定位是大学生,但现在它的用户范围已经扩大了很多。接着社交网站热潮席卷全球,而国内以人人网、开心网等为代表的社交网站也如雨后春笋般迅速崛起。社交网站极大地丰富了人们的社交生活,孕育了新的经济增长点,其所蕴含的巨大商业价值和社会力量也正凸显出来。
毫无疑问,目前世界上排名第一且分布最广的社交网站是脸书。脸书最大的特点就是可以非常方便地寻找朋友或联系老同学、老同事,能够简易地在朋友圈中分享图片、视频和音频文件(现在也可以发送其他文件,如.docx, .xlsx 等),以及通过集成的地图功能分享用户所在的位置。现在脸书的月度活跃用户已达 11.5 亿人之多,其中半数以上为移动电话用户。在 2010 年 3 月,脸书在美国的访问人数已超过谷歌,成为全美访问量最大的网站。脸书的官网域名为 Facebook.com,并持有.cn 域名 Facebook.cn。排名第二的社交网站是视频分享网站油管 YouTube,其月度活跃用户人数为 10 亿人。2006 年 YouTube.com 网站被谷歌收购,目前谷歌手上持有了 youtube.com/.com.cn/.net/.org 等域名。国内类似的视频分享网站有优酷 (www.youku.com)、土豆 (www.tudou.com)、56 网 (56.com) 等。
另一种能够提供微博服务的社交网络现在也很流行。例如推特 Twitter (twitter.com) 网站创建于 2006 年,它可以让用户发表不超过 140 个英文字符的消息。这些消息也被称为 “推文”(Tweet)。我国的新浪微博 (www.weibo.com)、腾讯微博 (t.qq.com) 等就是这种性质的社交网站。职业性社交网站领英 LinkedIn 也是很受欢迎的网站。
目前在我国最为流行的社交网站就是微信 (weixin.qq.com)。微信最初是专为手机用户使用的聊天工具,其功能是 “收发信息、拍照分享、联系朋友”。但几年来经过多次系统更新,现在微信不仅可传送文字短信、图片、录音电话、视频短片,还可提供实时音频或视频聊天,甚至可进行网上购物、转账、打车,等等。现在微信的功能已远远超越了社交领域。原来微信仅限于在手机上使用,但新的微信版本已能够安装在普通电脑上。我们知道,电子邮件可以发送给网上任何一个并不认识你的用户,也不管他是否愿意接收你发送的邮件。各种博客和微博也可供任何上网用户浏览。但微信只能在确定的朋友圈中交换信息。正是由于朋友之间更加需要交换信息,而微信的功能又不断在扩展,因此微信在我国已成为几乎每个网民都必备的应用软件。
6.5 电子邮件¶
6.5.1 电子邮件概述¶
大家知道,实时通信的电话固然使用方便,但有两个严重缺点。第一,电话通信的主叫和被叫双方必须同时在场。第二,有些电话常常不必要地打断被叫者的工作或休息。
电子邮件 (E-mail) 是互联网上使用最多的和最受用户欢迎的一种应用。电子邮件把邮件发送到收件人使用的邮件服务器,并放在其中的收件人邮箱 (mail box) 中,收件人可在自己方便时上网到自己使用的邮件服务器进行读取。这相当于互联网为用户设立了存放邮件的信箱,因此 e-mail 有时也称为 “电子信箱”。电子邮件不仅使用方便,而且还具有传递迅速和费用低廉的优点。据有的公司报道,使用电子邮件后可提高劳动生产率 30% 以上。现在电子邮件不仅可传送文字信息,而且还可附上声音和图像。由于电子邮件和手机的广泛使用,现已迫使传统的电报业务退出市场,因为这种传统电报既贵又慢,且很不方便。
1982 年 ARPANET 的电子邮件问世后,很快就成为最受广大网民欢迎的互联网应用。电子邮件的两个最重要的草案标准,是 2008 年更新的简单邮件传送协议 SMTP (Simple Mail Transfer Protocol) [RFC 5321] 和互联网文本报文格式 [RFC 5322]。
由于互联网的 SMTP 只能传送可打印的 7 位 ASCII 码邮件,因此在 1996 年又发布了通用互联网邮件扩充 MIME (Multipurpose Internet Mail Extensions)[RFC 2045,草案标准]。MIME 在其邮件首部中说明了邮件的数据类型(如文本、声音、图像、视像等)。在 MIME 邮件中可同时传送多种类型的数据。这在多媒体通信的环境下是非常有用的。
一个电子邮件系统应具有图 6-16 所示的三个主要组成构件,这就是用户代理、邮件服务器,以及邮件发送协议(如 SMTP)和邮件读取协议(如 POP3)。POP3 是邮局协议 (Post Office Protocol) 的版本 3。凡是有 TCP 连接的,都经过了互联网,有的甚至可以跨越数千公里的距离。这里为简洁起见,没有画出网络。在互联网中,邮件服务器的数量是很大的。正是这些邮件服务器构成了电子邮件基础结构的核心。在图 6-16 中为了说明问题,仅仅画出了两个邮件服务器。


用户代理 UA (User Agent) 就是用户与电子邮件系统的接口,在大多数情况下它就是运行在用户计算机中的一个程序。因此用户代理又称为电子邮件客户端软件。用户代理向用户提供一个很友好的接口(目前主要是窗口界面)来发送和接收邮件。现在可供大家选择的用户代理有很多种。例如,微软公司的 Outlook Express 和我国张小龙制作的 Foxmail,都是很受欢迎的电子邮件用户代理。
用户代理至少应当具有以下 4 个功能。
互联网上有许多邮件服务器可供用户选用(有些要收取少量的邮箱使用费用)。邮件服务器 24 小时不间断地工作,并且具有很大容量的邮件信箱。邮件服务器的功能是发送和接收邮件,同时还要向发件人报告邮件传送的结果(已交付、被拒绝、丢失等)。邮件服务器按照客户服务器方式工作。邮件服务器需要使用两种不同的协议。一种协议用于用户代理向邮件服务器发送邮件或在邮件服务器之间发送邮件,如 SMTP 协议,而另一种协议用于用户代理从邮件服务器读取邮件,如邮局协议 POP3。
这里应当注意,邮件服务器必须能够同时充当客户和服务器。例如,当邮件服务器 A 向另一个邮件服务器 B 发送邮件时,A 就作为 SMTP 客户,而 B 是 SMTP 服务器。反之,当 B 向 A 发送邮件时,B 就是 SMTP 客户,而 A 就是 SMTP 服务器。
图 6-16 给出了计算机之间发送和接收电子邮件的几个重要步骤。请注意,SMTP 和 POP3(或 IMAP)都是使用 TCP 连接来传送邮件的,使用 TCP 的目的是为了可靠地传送邮件。
请注意这里有两种不同的通信方式。一种是 “推”(push): SMTP 客户把邮件 “推” 给 SMTP 服务器。另一种是 “拉”(pull): POP3 客户把邮件从 POP3 服务器 “拉” 过来。细心的读者可能会想到这样的问题:如果让图 6-16 中的邮件服务器程序就在发送方和接收方的计算机中运行,那么岂不是可以直接把邮件发送到收件人的计算机中?
答案是 “不行”。这是因为并非所有的计算机都能运行邮件服务器程序。有些计算机可能没有足够的存储空间来运行允许程序在后台运行的操作系统,或是可能没有足够的 CPU 能力来运行邮件服务器程序。更重要的是,邮件服务器程序必须不间断地运行,每天 24 小时都必须不间断地连接在互联网上,否则就可能使很多外面发来的邮件无法接收。这样看来,让用户的计算机运行邮件服务器程序显然是很不现实的(一般用户在不使用计算机时就将机器关闭)。让来信暂时存储在用户的邮件服务器中,而当用户方便时就从邮件服务器的用户信箱中读取来信,则是一种比较合理的做法。在 Foxmail 中使用一种 “特快专递” 服务。这种服务就是从发件人的用户代理直接利用 SMTP 把邮件发送到接收方邮件服务器。这就加快了邮件的交付(省去在发送方邮件服务器中的排队等待时间)。但这种 “特快专递” 和邮政的 EMS 直接把邮件送到用户家中不同,它并没有把邮件直接发送到收件人的计算机中。但有些邮件服务器为了防止垃圾邮件和计算机病毒,拒绝接收从一般用户直接发来的邮件。
电子邮件由信封 (envelope) 和内容 (content) 两部分组成。电子邮件的传输程序根据邮件信封上的信息来传送邮件。这与邮局按照信封上的信息投递信件是相似的。
在邮件的信封上,最重要的就是收件人的地址。TCP/IP 体系的电子邮件系统规定电子邮件地址 (E-mail address) 的格式如下:
在式 (6-1) 中,符号 “@” 应读作 “at”,表示 “在” 的意思。例如,在电子邮件地址 “xyz@abc.com” 中,“abc.com” 就是邮件服务器的域名,而 “xyz” 就是在这个邮件服务器中收件人的用户名,也就是收件人邮箱名,是收件人为自己定义的字符串标识符。但应注意,这个用户名在邮件服务器中必须是唯一的(当用户定义自己的用户名时,邮件服务器要负责检查该用户名在本服务器中的唯一性)。这样就保证了每一个电子邮件地址在世界范围内是唯一的。这对保证电子邮件能够在整个互联网范围内的准确交付是十分重要的。电子邮件的用户一般采用容易记忆的字符串。
6.5.2 简单邮件传送协议 SMTP¶
下面介绍 SMTP 的一些主要特点。
SMTP 规定了在两个相互通信的 SMTP 进程之间应如何交换信息。由于 SMTP 使用客户服务器方式,因此负责发送邮件的 SMTP 进程就是 SMTP 客户,而负责接收邮件的 SMTP 进程就是 SMTP 服务器。至于邮件内部的格式,邮件如何存储,以及邮件系统应以多快的速度来发送邮件,SMTP 也都未做出规定。
SMTP 规定了 14 条命令和 21 种应答信息。每条命令用几个字母组成,而每一种应答信息一般只有一行信息,由一个 3 位数字的代码开始,后面附上(也可不附上)很简单的文字说明。下面通过发送方和接收方的邮件服务器之间的 SMTP 通信的三个阶段介绍几个最主要的命令和响应信息。
1. 连接建立¶
发件人的邮件送到发送方邮件服务器的邮件缓存后,SMTP 客户就每隔一定时间(例如 30 分钟)对邮件缓存扫描一次。如发现有邮件,就使用 SMTP 的熟知端口号码 25 与接收方邮件服务器的 SMTP 服务器建立 TCP 连接。在连接建立后,接收方 SMTP 服务器要发出 “220 Service ready”(服务就绪)。然后 SMTP 客户向 SMTP 服务器发送 HELO 命令,附上发送方的主机名。SMTP 服务器若有能力接收邮件,则回答:“250 OK”,表示已准备好接收。若 SMTP 服务器不可用,则回答 “421 Service not available”(服务不可用)。
如在一定时间内(例如三天)发送不了邮件,邮件服务器会把这个情况通知发件人。
SMTP 不使用中间的邮件服务器。不管发送方和接收方的邮件服务器相隔有多远,不管在邮件传送过程中要经过多少个路由器,TCP 连接总是在发送方和接收方这两个邮件服务器之间直接建立。当接收方邮件服务器出故障而不能工作时,发送方邮件服务器只能等待一段时间后再尝试和该邮件服务器建立 TCP 连接,而不能先找一个中间的邮件服务器建立 TCP 连接。
2. 邮件传送¶
邮件的传送从 MAIL 命令开始。MAIL 命令后面有发件人的地址。如:MAIL FROM: xiexiren@tsinghua.org.cn。若 SMTP 服务器已准备好接收邮件,则回答 “250 OK”。否则,返回一个代码,指出原因。如:451(处理时出错)、452(存储空间不够)、500(命令无法识别)等。
下面跟着一个或多个 RCPT 命令,取决于把同一个邮件发送给一个或多个收件人,其格式为 RCPT TO: <收件人地址>。RCPT 是 recipient(收件人)的缩写。每发送一个 RCPT 命令,都应当有相应的信息从 SMTP 服务器返回,如:“250 OK”,表示指明的邮箱在接收方的系统中,或 “550 No such user here”(无此用户),即不存在此邮箱。
RCPT 命令的作用就是:先弄清接收方系统是否已做好接收邮件的准备,然后才发送邮件。这样做是为了避免浪费通信资源,不至于发送了很长的邮件以后才知道地址错误。
再下面就是 DATA 命令,表示要开始传送邮件的内容了。SMTP 服务器返回的信息是:“354 Start mail input; end with
虽然 SMTP 使用 TCP 连接试图使邮件的传送可靠,但 “发送成功” 并不等于 “收件人读取了这个邮件”。当一个邮件传送到接收方的邮件服务器后(即接收方的邮件服务器收下了这个邮件),再往后的情况如何,就有以下几种可能性:
(1) 接收方的邮件服务器刚收到邮件后就出了故障,使收到的邮件全部丢失(在收件人读取信件之前)。
(2) 收件人由于某种原因,未检查自己的邮箱,不知道邮箱中有新的来信。
(3) 收件人很长时间不删除邮箱中的过期邮件,导致有限的邮箱容量用尽,无法再接收新的邮件。
(4) 邮件服务器根据某种原则,误判某些邮件属于垃圾邮件,就把收到的某些邮件转入到垃圾邮件的文件夹。收件人应从垃圾邮件的文件夹中清理出未收到的非垃圾邮件。
因此,使用电子邮件的人,应当养成及时收取和清理自己的邮箱的好习惯。
3. 连接释放¶
邮件发送完毕后,SMTP 客户应发送 QUIT 命令。SMTP 服务器返回的信息是 “221(服务关闭)”,表示 SMTP 同意释放 TCP 连接。邮件传送的全部过程即结束。
这里再强调一下,使用电子邮件的用户看不见以上这些过程,所有这些复杂过程都被电子邮件的用户代理屏蔽了。
已经广泛使用多年的 SMTP 存在着一些缺点。例如,发送电子邮件不需要经过鉴别。这就是说,在 FROM 命令后面的地址可以任意填写。这就大大方便了垃圾邮件的作者,给收信人添加了麻烦(有人估计,在全世界所有的电子邮件中,垃圾邮件至少占到 50% 以上,甚至高达 90%)。又如,SMTP 本来就是为传送 ASCII 码而不是传送二进制数据设计的。虽然后来有了 MIME 可以传送二进制数据(见后面 6.5.6 节的介绍),但在传送非 ASCII 码的长报文时,在网络上的传输效率是不高的。此外,SMTP 传送的邮件是明文,不利于保密。
为了解决上述问题,2008 年 10 月颁布的草案标准 RFC5321 对 SMTP 进行了扩充,成为扩充的 SMTP (Extended SMTP),记为 ESMTP。RFC5321 在许多命令中增加了扩展的参数。新增加的功能有:客户端的鉴别,服务器接受二进制报文,服务器接受分块传送的大报文,发送前先检查报文的大小,使用安全传输 TLS(见下一章 7.6.2 节),以及使用国际化地址等。考虑到现在的许多 SMTP 邮件服务器可能还没有升级到 ESMTP,因此特规定使用 ESMTP 的客户端在准备传送报文时,不是发送 HELO 而是发送 EHLO 报文。如果 EHLO 报文被对方服务器端拒绝,就表明对方仍然是一个标准的 SMTP 邮件服务器(不使用扩展的参数),因而就要按照原来使用的 SMTP 参数进行邮件的传送。如果 EHLO 报文被接受了,那么客户端就可以使用 ESMTP 扩展的参数传送报文了。
6.5.3 电子邮件的信息格式¶
一个电子邮件分为信封和内容两大部分。在草案标准 RFC 5322 文档中只规定了邮件内容中的首部 (header) 格式,而对邮件的主体 (body) 部分则让用户自由撰写。用户写好首部后,邮件系统自动地将信封所需的信息提取出来并写在信封上。所以用户不需要填写电子邮件信封上的信息。
邮件内容首部包括一些关键字,后面加上冒号。最重要的关键字是:To 和 Subject。
“To:” 后面填入一个或多个收件人的电子邮件地址。在电子邮件软件中,用户把经常通信的对象姓名和电子邮件地址写到地址簿 (address book) 中。当撰写邮件时,只需打开地址簿,点击收件人名字,收件人的电子邮件地址就会自动地填入到合适的位置上。
“Subject:” 是邮件的主题。它反映了邮件的主要内容。主题类似于文件系统的文件名,便于用户查找邮件。
邮件首部还有一项是抄送 “Cc:”。这两个字符来自 “Carbon copy”,意思是留下一个 “复写副本”。这是借用旧的名词,表示应给某某人发送一个邮件副本。
有些邮件系统允许用户使用关键字 Bcc (Blind carbon copy) 来实现盲复写副本。这是使发件人能将邮件的副本送给某人,但不希望此事为收件人知道。Bcc 又称为暗送。
首部关键字还有 “From” 和 “Date”,表示发件人的电子邮件地址和发信日期。这两项一般都由邮件系统自动填入。
另一个关键字是 “Reply-To”,即对方回信所用的地址。这个地址可以与发件人发信时所用的地址不同。例如有时到外地借用他人的邮箱给自己的朋友发送邮件,但仍希望对方将回信发送到自己的邮箱。这一项可以事先设置好,不需要在每次写信时进行设置。
6.5.4 邮件读取协议 POP3 和 IMAP¶
现在常用的邮件读取协议有两个,即邮局协议第 3 个版本 POP3 和网际报文存取协议 IMAP (Internet Message Access Protocol)。现分别讨论如下。
邮局协议 POP 是一个非常简单、但功能有限的邮件读取协议。邮局协议 POP 最初公布于 1984 年。经过几次更新,现在使用的是 1996 年的版本 POP3 [RFC 1939, STD53],大多数的 ISP 都支持 POP3。
POP3 也使用客户服务器的工作方式。在接收邮件的用户计算机中的用户代理必须运行 POP3 客户程序,而在收件人所连接的 ISP 的邮件服务器中则运行 POP3 服务器程序。当然,这个 ISP 的邮件服务器还必须运行 SMTP 服务器程序,以便接收发送方邮件服务器的 SMTP 客户程序发来的邮件。这些请参阅图 6-16。POP3 服务器只有在用户输入鉴别信息(用户名和口令)后,才允许对邮箱进行读取。
POP3 协议的一个特点就是只要用户从 POP3 服务器读取了邮件,POP3 服务器就把该邮件删除。这在某些情况下就不够方便。例如,某用户在办公室的台式计算机上接收了一个邮件,还来不及写回信,就马上携带笔记本电脑出差。当他打开笔记本电脑写回信时,POP3 服务器上却已经删除了原来已经看过的邮件(除非他事先将这些邮件复制到笔记本电脑中)。为了解决这一问题,POP3 进行了一些功能扩充,其中包括让用户能够事先设置邮件读取后仍然在 POP3 服务器中存放的时间 [RFC 2449,建议标准]。
另一个读取邮件的协议是网际报文存取协议 IMAP,它比 POP3 复杂得多。IMAP 和 POP 都按客户服务器方式工作,但它们有很大的差别。现在较新的版本是 2003 年 3 月修订的版本 4,即 IMAP4 [RFC 3501,建议标准]。不过在习惯上,对这个协议大家很少加上版本号 “4”,而经常简单地用 IMAP 表示 IMAP4。但是对 POP3 却不会忘记写上版本号 “3”。
在使用 IMAP 时,在用户的计算机上运行 IMAP 客户程序,然后与接收方的邮件服务器上的 IMAP 服务器程序建立 TCP 连接。用户在自己的计算机上就可以操纵邮件服务器的邮箱,就像在本地操纵一样,因此 IMAP 是一个联机协议。当用户计算机上的 IMAP 客户程序打开 IMAP 服务器的邮箱时,用户就可看到邮件的首部。若用户需要打开某个邮件,则该邮件才传到用户的计算机上。用户可以根据需要为自己的邮箱创建便于分类管理的层次式的邮箱文件夹,并且能够将存放的邮件从某一个文件夹中移动到另一个文件夹中。用户也可按某种条件对邮件进行查找。在用户未发出删除邮件的命令之前,IMAP 服务器邮箱中的邮件一直保存着。
IMAP 最大的好处就是用户可以在不同的地方使用不同的计算机(例如,使用办公室的计算机、或家中的计算机,或在外地使用笔记本电脑)随时上网阅读和处理自己在邮件服务器中的邮件。IMAP 还允许收件人只读取邮件中的某一个部分。例如,收到了一个带有视像附件(此文件可能很大)的邮件,而用户使用的是无线上网,信道的传输速率很低。为了节省时间,可以先下载邮件的正文部分,待以后有时间再读取或下载这个很大的附件。
IMAP 的缺点是如果用户没有将邮件复制到自己的计算机上,则邮件一直存放在 IMAP 服务器上。要想查阅自己的邮件,必须先上网。
下面的表 6-2 给出了 IMAP 和 POP3 的主要功能的比较。
表 6-2 IMAP 和 POP3 的主要功能比较
| 操作位置 | 操作内容 | IMAP | POP3 |
| 收件箱 | 阅读、标记、移动、删除邮件等 | 客户端与邮箱更新同步 | 仅在客户端内 |
| 发件箱 | 保存到已发送 | 客户端与邮箱更新同步 | 仅在客户端内 |
| 创建文件夹 | 新建自定义的文件夹 | 客户端与邮箱更新同步 | 仅在客户端内 |
| 草稿 | 保存草稿 | 客户端与邮箱更新同步 | 仅在客户端内 |
| 垃圾文件夹 | 接收并移入垃圾文件夹的邮件 | 支持 | 不支持 |
| 广告邮件 | 接收并移入广告邮件夹的邮件 | 支持 | 不支持 |
最后再强调一下,不要把邮件读取协议 POP3 或 IMAP 与邮件传送协议 SMTP 弄混。发件人的用户代理向发送方邮件服务器发送邮件,以及发送方邮件服务器向接收方邮件服务器发送邮件,都是使用 SMTP 协议。而 POP3 或 IMAP 则是用户代理从接收方邮件服务器上读
取邮件所使用的协议。
6.5.5 基于万维网的电子邮件¶
从前面的图 6-16 可看出,用户要使用电子邮件,必须在自己使用的计算机中安装用户代理软件 UA。如果外出到某地而又未携带自己的笔记本电脑,那么要使用别人的计算机进行电子邮件的收发,将是非常不方便的。
现在这个问题解决了。在 20 世纪 90 年代中期,Hotmail 推出了基于万维网的电子邮件 (Webmail)。今天,几乎所有的著名网站以及大学或公司,都提供了万维网电子邮件。常用的万维网电子邮件有谷歌的 Gmail (@gmail.com),微软的 Hotmail (@hotmail.com),雅虎的 Yahoo 邮箱 (@yahoo.com)。我国的互联网技术公司也都提供万维网邮件服务,例如,网易邮箱 (@163.com 或 @126.com)、新浪邮箱 (@sina.com 或 @sina.cn) 和腾讯的 QQ 邮箱 (@qq.com) 等。
万维网电子邮件的好处就是:不管在什么地方(在任何一个国家的网吧、宾馆或朋友家中),只要能够找到上网的计算机,在打开任何一种浏览器后,就可以非常方便地收发电子邮件。使用万维网电子邮件不需要在计算机中再安装用户代理软件。浏览器本身可以向用户提供非常友好的电子邮件界面(和原来的用户代理提供的界面相似),使用户在浏览器上就能够很方便地撰写和收发电子邮件。
例如,你使用的是网易的 163 邮箱,那么在任何一个浏览器的地址栏中,键入 163 邮箱的 URL (mail.163.com),按回车键后,就可以使用 163 电子邮件了,这和在家中一样方便。你曾经接收和发送过的邮件、已删除的邮件以及你的通信录等内容,都照常呈现在屏幕上。
我们知道,用户在浏览器中浏览各种信息时需要使用 HTTP 协议。因此,在浏览器和互联网上的邮件服务器之间传送邮件时,仍然使用 HTTP 协议。但是在各邮件服务器之间传送邮件时,则仍然使用 SMTP 协议。
6.5.6 通用互联网邮件扩充 MIME¶
1. MIME 概述¶
前面所述的电子邮件协议 SMTP 有以下缺点:
- 将制表符 tab 转换为若干个空格。
于是在这种情况下就提出了通用互联网邮件扩充 MIME [RFC 2045\~2049,前三个文档是草案标准]。MIME 并没有改动或取代 SMTP。MIME 的意图是继续使用原来的邮件格式,但增加了邮件主体的结构,并定义了传送非 ASCII 码的编码规则。也就是说,MIME 邮件可在现有的电子邮件程序和协议下传送。图 6-17 表示 MIME 和 SMTP 的关系。

MIME 主要包括以下三部分内容:
为适应于任意数据类型和表示,每个 MIME 报文包含告知收件人数据类型和使用编码的信息。MIME 把增加的信息加入到原来的邮件首部中。
下面是 MIME 增加的 5 个新的邮件首部的名称及其意义(有的可以是选项)。
上述的前三项的意思很清楚,因此下面只对后两项进行介绍。
2. 内容传送编码¶
下面介绍三种常用的内容传送编码 (Content-Transfer-Encoding)。
最简单的编码就是 7 位 ASCII 码,而每行不能超过 1000 个字符。MIME 对这种由 ASCII 码构成的邮件主体不进行任何转换。
另一种编码称为 quoted-printable,这种编码方法适用于所传送的数据中只有少量的非 ASCII 码,例如汉字。这种编码方法的要点就是对于所有可打印的 ASCII 码,除特殊字符等号 “=” 外,都不改变。等号 “=” 和不可打印的 ASCII 码以及非 ASCII 码的数据的编码方法是:先将每个字节的二进制代码用两个十六进制数字表示,然后在前面再加上一个等号 “=”。例如,汉字的 “系统” 的二进制编码是:11001111 10110101 11001101 10110011(共有 32 位,但这四个字节都不是 ASCII 码),其十六进制数字表示为:CFB5CDB3。用 quoted-printable 编码表示为:=CF=B5=CD=B3,这 12 个字符都是可打印的 ASCII 字符,它们的二进制编码 \(^{①}\) 需要 96 位,和原来的 32 位相比,开销达 200%。而等号 “=” 的二进制代码为 00111101,即十六进制的 3D,因此等号 “=” 的 quoted-printable 编码为 “=3D”。
对于任意的二进制文件,可用 base64 编码。这种编码方法是先把二进制代码划分为一个个 24 位长的单元,然后把每一个 24 位单元划分为 4 个 6 位组。每一个 6 位组按以下方法转换成 ASCII 码。6 位的二进制代码共有 64 种不同的值,从 0 到 63。用 A 表示 0,用 B 表示 1,等等。26 个大写字母排列完毕后,接下去再排 26 个小写字母,再后面是 10 个数字,最后用 “+” 表示 62,而用 “/” 表示 63。再用两个连在一起的等号 “==” 和一个等号 “=” 分别表示最后一组的代码只有 8 位或 16 位。回车和换行都忽略,它们可在任何地方插入。
下面是一个 base64 编码的例子:
| 24位二进制代码 | 01001001 00110001 01111001 | |||
| 划分为4个6位组 | 010010 | 010011 | 000101 | 111001 |
| 对应的base64编码 | S | T | F | 5 |
| 用ASCII编码发送 | 01010011 | 01010100 | 01000110 | 00110101 |
不难看出,24 位的二进制代码采用 base64 编码后变成了 32 位,开销为 8 位,占 32 位的 25%。
3. 内容类型¶
MIME 标准规定 Content-Type 说明必须含有两个标识符,即内容类型 (type) 和子类型 (subtype),中间用 “/” 分开。
MIME 一直到现在还是草案标准。除了内容类型和子类型,MIME 允许发件人和收件人自己定义专用的内容类型。但为避免可能出现名字冲突,标准要求为专用的内容类型选择的名字要以字符串 X - 开始。后来陆续出现了几百个子类型,而且子类型的数目还在不断地增加。现在可以在网站上查出现有的 MIME 类型和子类型的名称,以及申请新的子类型的具体步骤 [W-MEDIA-TYPE]。表 6-3 列出了 MIME 常用的内容类型、子类型举例及其说明 \(^{②}\) 。
表 6-3 可出现在 MIME Content-Type 说明中的类型及子类型举例
| 内容类型 | 子类型举例 | 说明 |
| text(文本) | plain, html, xml, css | 不同格式的文本 |
| image(图像) | gif, jpeg, tiff | 不同格式的静止图像 |
| audio(音频) | basic, mpeg, mp4 | 可听见的声音 |
| video(视频) | mpeg, mp4, quicktime | 不同格式的影片 |
| model(模型) | vrml | 3D 模型 |
| application(应用) | octet-stream, pdf, javascript, zip | 不同应用程序产生的数据 |
| message(报文) | http, rfc822 | 封装的报文 |
| multipart(多部分) | mixed, alternative, parallel, digest | 多种类型的组合 |
MIME 的内容类型中的 multipart 是很有用的,因为它使邮件增加了相当大的灵活性。MIME 标准为 multipart 定义了四种可能的子类型,每个子类型都提供重要功能。
下面显示了一个 MIME 邮件,它包含有一个简单解释的文本和含有非文本信息的照片。邮件中第一部分的注解说明第二部分含有一张照片。
From: xiexiren@tsinghua.org.cn
To: xyz@163.com
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=qwertyuiop
--qwertyuiop
XYZ:
你要的图片在此邮件中,收到后请回信。
谢希仁
--qwertyuiop
Content-Type: image/gif
Content-Transfer-Encoding: base64
...data for the image (图像的数据)...
--qwertyuiop--
上面最后一行表示 boundary 的字符串后面还有两个连字符 “--”,表示整个 multipart 的结束。
6.6 动态主机配置协议 DHCP¶
为了把协议软件做成通用的和便于移植的,协议软件的编写者不会把所有的细节都固定在源代码中。相反,他们把协议软件参数化。这就使得在很多台计算机上有可能使用同一个经过编译的二进制代码。一台计算机和另一台计算机的许多区别,都可以通过一些不同的参数来体现。在协议软件运行之前,必须给每一个参数赋值。
在协议软件中给这些参数赋值的动作叫作协议配置。一个协议软件在使用之前必须是已正确配置的。具体的配置信息有哪些则取决于协议栈。例如,连接到互联网的计算机的协议软件需要配置的项目包括:
为了省去给计算机配置 IP 地址的麻烦,我们能否在计算机的生产过程中,事先给每一台计算机配置好一个唯一的 IP 地址呢(如同每一个以太网适配器拥有一个唯一的 MAC 地址)?这显然是不行的。这是因为 IP 地址不仅包括了主机号,而且还包括了网络号。一个 IP 地址指出了一台计算机连接在哪一个网络上。当计算机还在生产时,无法知道它在出厂后将被连接到哪一个网络上。因此,需要连接到互联网的计算机,必须对 IP 地址等项目进行协议配置。
用人工进行协议配置很不方便,而且容易出错。因此,应当采用自动协议配置的方法。
互联网现在广泛使用的是动态主机配置协议 DHCP (Dynamic Host Configuration Protocol),它提供了一种机制,称为即插即用连网 (plug-and-play networking)。这种机制允许一台计算机加入新的网络和获取 IP 地址而不用手工参与。DHCP 最新的 RFC 文档还是互联网草案标准 [RFC 2131—2132]。
DHCP 对运行客户软件和服务器软件的计算机都适用。当运行客户软件的计算机移至一个新的网络时,就可使用 DHCP 获取其配置信息而不需要手工干预。DHCP 给运行服务器软件而位置固定的计算机指派一个永久地址,而当这计算机重新启动时其地址不改变。
DHCP 使用客户服务器方式。需要 IP 地址的主机在启动时就向 DHCP 服务器广播发送发现报文 (DHCPDISCOVER)(将目的 IP 地址置为全 1,即 255.255.255.255),这时该主机就成为 DHCP 客户。发送广播报文是因为现在还不知道 DHCP 服务器在什么地方,因此要发现 (DISCOVER) DHCP 服务器的 IP 地址。这台主机目前还没有自己的 IP 地址,因此它将 IP 数据报的源 IP 地址设为全 0。这样,在本地网络上的所有主机都能够收到这个广播报文,但只有 DHCP 服务器才对此广播报文进行回答。DHCP 服务器先在其数据库中查找该计算机的配置信息。若找到,则返回找到的信息。若找不到,则从服务器的 IP 地址池 (address pool) 中取一个地址分配给该计算机。DHCP 服务器的回答报文叫作提供报文 (DHCPOFFER),表示 “提供” 了 IP 地址等配置信息。
但是我们并不愿意在每一个网络上都设置一个 DHCP 服务器,因为这样会使 DHCP 服务器的数量太多。因此现在是使每一个网络至少有一个 DHCP 中继代理 (relay agent)(通常是一台路由器,如图 6-18 所示),它配置了 DHCP 服务器的 IP 地址信息。当 DHCP 中继代理收到主机 A 以广播形式发送的发现报文后,就以单播方式向 DHCP 服务器转发此报文,并等待其回答。收到 DHCP 服务器回答的提供报文后,DHCP 中继代理再把此提供报文发回给主机 A。需要注意的是,图 6-18 只是个示意图。实际上,DHCP 报文只是 UDP 用户数据报的数据,它还要加上 UDP 首部、IP 数据报首部,以及以太网的 MAC 帧的首部和尾部后,才能在链路上传送。

DHCP 服务器分配给 DHCP 客户的 IP 地址是临时的,因此 DHCP 客户只能在一段有限的时间内使用这个分配到的 IP 地址。DHCP 协议称这段时间为租用期 (lease period),但并没有具体规定租用期应取为多长或至少为多长,这个数值应由 DHCP 服务器自己决定。例如,一个校园网的 DHCP 服务器可将租用期设定为 1 小时。DHCP 服务器在给 DHCP 发送的提供报文的选项中给出租用期的数值。按照 RFC 2132 的规定,租用期用 4 字节的二进制数字表示,单位是秒。因此可供选择的租用期范围从 1 秒到 136 年。DHCP 客户也可在自己发送的报文中(例如,发现报文)提出对租用期的要求。
DHCP 的详细工作过程如图 6-19 所示。DHCP 客户使用的 UDP 端口是 68,而 DHCP 服务器使用的 UDP 端口是 67。这两个 UDP 端口都是熟知端口。

下面按照图 6-19 中的注释编号(①至⑨)进行简单的解释。

可能收到多个 DHCP 提供报文。
④ DHCP 客户从几个 DHCP 服务器中选择其中的一个,并向所选择的 DHCP 服务器发送 DHCP 请求报文。
⑤ 被选择的 DHCP 服务器发送确认报文 DHCPACK。从这时起,DHCP 客户就可以使用这个 IP 地址了。这种状态叫作已绑定状态,因为在 DHCP 客户端的 IP 地址和 MAC 地址已经完成绑定,并且可以开始使用得到的临时 IP 地址了。
DHCP 客户现在要根据服务器提供的租用期 T 设置两个计时器 \(T_{1}\) 和 \(T_{2}\) ,它们的超时时间分别是 0.5T 和 0.875T。当超时时间到了就要请求更新租用期。
⑥ 租用期过了一半( \(T_{1}\) 时间到),DHCP 客户发送请求报文 DHCPREQUEST 要求更新租用期。
⑦ DHCP 服务器若同意,则发回确认报文 DHCPACK。DHCP 客户得到了新的租用期,重新设置计时器。
⑧ DHCP 服务器若不同意,则发回否认报文 DHCPNACK。这时 DHCP 客户必须立即停止使用原来的 IP 地址,而必须重新申请 IP 地址(回到步骤②)。
若 DHCP 服务器不响应步骤⑥的请求报文 DHCPREQUEST,则在租用期过了 87.5% 时( \(T_{2}\) 时间到),DHCP 客户必须重新发送请求报文 DHCPREQUEST(重复步骤⑥),然后又继续后面的步骤。
⑨ DHCP 客户可以随时提前终止服务器所提供的租用期,这时只需向 DHCP 服务器发送释放报文 DHCPRELEASE 即可。
DHCP 很适合于经常移动位置的计算机。当计算机使用 Windows 操作系统时,点击 “控制面板” 的 “网络” 图标就可以找到某个连接中的 “网络” 下面的菜单,找到 TCP/IP 协议后点击其 “属性” 按钮,若选择 “自动获得 IP 地址” 和 “自动获得 DNS 服务器地址” 选项,就表示是使用 DHCP 协议。
6.7 简单网络管理协议 SNMP¶
6.7.1 网络管理的基本概念¶
虽然网络管理还没有精确定义,但它的内容可归纳为:
网络管理包括对硬件、软件和人力的使用、综合与协调,以便对网络资源进行监视、测试、配置、分析、评价和控制,这样就能以合理的价格满足网络的一些需求,如实时运行性能、服务质量等。网络管理常简称为网管。
我们可以看到,网络管理并不是指对网络进行行政上的管理。
网络是一个非常复杂的分布式系统。这是因为网络上有很多不同厂家生产的、运行着多种协议的节点(主要是路由器),而这些节点还在相互通信和交换信息。网络的状态总是不断地变化着。可见,我们必须使用一种机制来读取这些节点上的状态信息,有时还要把一些新的状态信息写入到这些节点上。
下面简单介绍网络管理模型中的主要构件(如图 6-20 所示)。
管理站又称为管理器,是整个网络管理系统的核心,它通常是个有着良好图形界面的高性能的工作站,并由网络管理员直接操作和控制。所有向被管设备发送的命令都是从管理站发出的。管理站的所在部门也常称为网络运行中心 NOC (Network Operations Center)。管理站中的关键构件是管理程序(如图 6-20 中有字母 M 的椭圆形图标所示)。管理程序在运行时就成为管理进程。管理站(硬件)或管理程序(软件)都可称为管理者 (manager) 或管理器,所以这里的 manager 不是指人而是指机器或软件。网络管理员 (administrator) 才是指人。大型网络往往实行多级管理,因而有多个管理者,而一个管理者一般只管理本地网络的设备。

在被管网络中有很多的被管设备(包括设备中的软件)。被管设备可以是主机、路由器、打印机、集线器、网桥或调制解调器等。在每一个被管设备中可能有许多被管对象 (Managed Object)。被管对象可以是被管设备中的某个硬件(例如,一块网络接口卡),也可以是某些硬件或软件(例如,路由选择协议)的配置参数的集合。被管设备有时可称为网络元素或简称为网元。在被管设备中也会有一些不能被管的对象(在下面的 6.7.2 节将会讲到对象命名树,所谓不能被管的对象就是不在对象命名树上的对象)。
在每一个被管设备中都要运行一个程序以便和管理站中的管理程序进行通信。这些运行着的程序叫作网络管理代理程序,或简称为代理 (agent)(如图 6-20 中有字母 A 的几个椭圆形图标所示)。代理程序在管理程序的命令和控制下,在被管设备上采取本地的行动。
在图 6-20 中还有一个重要构件就是网络管理协议,简称为网管协议。后面还要讨论它的作用。
简单网络管理协议 SNMP (Simple Network Management Protocol) 中的管理程序和代理程序按客户服务器方式工作。管理程序运行 SNMP 客户程序,而代理程序运行 SNMP 服务器程序。在被管对象上运行的 SNMP 服务器程序不停地监听来自管理站的 SNMP 客户程序的请求(或命令)。一旦发现了,就立即返回管理站所需的信息,或执行某个动作(例如,把某个参数的设置进行更新)。在网管系统中往往是一个(或少数几个)客户程序与很多的服务器程序进行交互。
关于网络管理有一个基本原理,这就是:
若要管理某个对象,就必然会给该对象添加一些软件或硬件,但这种 “添加” 对原有对象的影响必须尽量小些。
SNMP 正是按照这样的基本原理来设计的。
SNMP 发布于 1988 年。OSI 虽然在这之前就已制定出许多的网络管理标准,但当时(到现在也很少)却没有符合 OSI 网管标准的产品。SNMP 最重要的指导思想就是要尽可能简单。SNMP 的基本功能包括监视网络性能、检测分析网络差错和配置网络设备等。在网络正常工作时,SNMP 可实现统计、配置和测试等功能。当网络出故障时,可实现各种差错检测和恢复功能。经过近二十年的使用,SNMP 不断修订完善,较新的版本是 SNMPv3,而前两个版本分别是 SNMPv2 和 SNMPv1。但一般可简称为 SNMP。SNMPv3 最大的改进就是安全特性。也就是说,只有被授权的人员才有资格执行网络管理的功能(如关闭某一条链路)和读取有关网络管理的信息(如读取一个配置文件的内容)。然而 SNMP 协议已相当庞大,一点也不 “简单”,整个标准共有八个 RFC 文档 [RFC 3411—3418,STD62]。因此这里只能给出一些最基本的概念。
若网络元素使用的不是 SNMP 协议而是另一种网络管理协议,那么 SNMP 协议就无法控制该网络元素。这时可使用委托代理 (proxy agent)。委托代理能提供如协议转换和过滤操作等功能对被管对象进行管理。
SNMP 的网络管理由三个部分组成,即 SNMP 本身、管理信息结构 SMI (Structure of Management Information) 和管理信息库 MIB (Management Information Base)。下面简述这三部分的作用。
SNMP 定义了管理站和代理之间所交换的分组格式。所交换的分组包含各代理中的对象(变量)名及其状态(值)。SNMP 负责读取和改变这些数值。
SMI 定义了命名对象和定义对象类型(包括范围和长度)的通用规则,以及把对象和对象的值进行编码的规则。这样做是为了确保网络管理数据的语法和语义无二义性。但从 SMI 的名称并不能看出它的功能。请注意,SMI 并不定义一个实体应管理的对象数目,也不定义被管对象名以及对象名及其值之间的关联。
MIB 在被管理的实体中创建了命名对象,并规定了其类型。
为了更好地理解上述的几个组成部分,可以把它们和程序设计进行一下对比。
我们在编程时要使用某种语言,而这种语言就是用来定义编程的规则。例如,一个变量名必须从字母开始而后面接着是字母数字。在网络管理中,这些规则由 SMI 来定义。
在程序设计中必须对变量进行说明。例如,int counter,表示变量 counter 是整数类型。MIB 在网络管理中就做这样的事情。MIB 给每个对象命名,并定义对象的类型。
在编程中的说明语句之后,程序需要写出一些语句用来存储变量的值,并在需要时改变这些变量的值。协议 SNMP 在网络管理中完成这件任务。SNMP 按照 SMI 定义的规则,存储、改变和解释这些已由 MIB 说明的对象的值。
总之,SMI 建立规则,MIB 对变量进行说明,而 SNMP 完成网管的动作。
下面就一一介绍上述的三个构件。
6.7.2 管理信息结构 SMI¶
管理信息结构 SMI 是 SNMP 的重要组成部分。根据 6.7.1 节所讲,SMI 的功能应当有三个,即规定:
1. 被管对象的命名¶
SMI 规定,所有的被管对象都必须处在对象命名树 (object naming tree) 上。图 6-21 给出了对象命名树的一部分。对象命名树的根没有名字,它的下面有三个顶级对象,都是世界上著名的标准制定单位,即 ITU-T(过去叫作 CCITT)和 ISO,以及这两个组织的联合体,它们的标号分别是 0 到 2。图中的对象名习惯上用英文小写表示。在 ISO 的下面的一个标号为 3 的节点是 ISO 认同的组织成员 org。在其下面有一个美国国防部 dod (Department of Defense) 的子树(标号为 6),再下面就是 internet(标号为 1)。在只讨论 internet 中的对象时,可只画出 internet 以下的子树,并在 internet 节点旁边写上对象标识符 1.3.6.1 即可。

在 internet 节点下面的标号为 2 的节点是 mgmt(管理)。再下面只有一个节点,即管理信息库 mib-2,其对象标识符为 1.3.6.1.2.1。在 mib-2 下面包含了所有被 SNMP 管理的对象(见下面 6.7.3 节的讨论)。
2. 被管对象的数据类型¶
SMI 使用基本的抽象语法记法 1(即 ISO 制定的 ASN.1 \(^{①}\) )来定义数据类型,但又增加了一些新的定义。因此 SMI 既是 ASN.1 的子集,又是 ASN.1 的超集。ASN.1 的记法很严格,它使得数据的含义不存在任何可能的二义性。例如,使用 ASN.1 时不能简单地说 “一个具有整数值的变量”,而必须说明该变量的准确格式和整数取值的范围。当网络中的计算机对数据项并不都使用相同的表示时,采用这种精确的记法就尤其重要。
我们知道,任何数据都具有两种重要的属性,即值 (value) 与类型 (type)。这里 “值” 是某个值集合中的一个元素,而 “类型” 则是值集合的名字。如果给定一种类型,则这种类型的一个值就是该类型的一个具体实例。
SMI 把数据类型分为两大类:简单类型和结构化类型。简单类型是最基本的、直接使用 ASN.1 定义的类型。表 6-4 给出了最主要的几种简单类型。
表 6-4 几种最主要的简单类型
| 类型 | 大小 | 说明 |
| INTEGER | 4 字节 | 在 $-2^{31}$ 到 $2^{31}-1$ 之间的整数 |
| Interger32 | 4 字节 | 和 INTEGER 相同 |
| Unsigned32 | 4 字节 | 在 0 到 $2^{32}-1$ 之间的无符号数 |
| OCTET STRING | 可变 | 不超过 65535 字节长的字节串 |
| OBJECT IDENTIFIER | 可变 | 对象标识符 |
| IPAddress | 4 字节 | 由 4 个整数组成的 IP 地址 |
| Counter32 | 4 字节 | 可从 0 增加到 $2^{32}$ 的整数;当它到达最大值时就返回到 0 |
| TimeTicks | 4 字节 | 记录时间的计数值,以 1/100 秒为单位 |
| BITS | — | 比特串 |
| Opaque | 可变 | 不解释的串 |
SMI 定义了两种结构化数据类型,即 sequence 和 sequence of。
数据类型 sequence 类似于 C 语言中的 struct 或 record,它是一些简单数据类型的组合(不一定要相同的类型)。而数据类型 sequence of 类似于 C 语言中的 array,它是同样类型的简单数据类型的组合,或同样类型的 sequence 数据类型的组合。
3. 编码方法¶
SMI 使用 ASN.1 制定的基本编码规则 BER (Basic Encoding Rule) 进行数据的编码。BER 指明了每种数据的类型和值。在发送端用 BER 编码,可把用 ASN.1 所表述的报文转换成唯一的比特序列。在接收端用 BER 进行解码,就可得到该比特序列所表示的 ASN.1 报文。
初看起来,或许用两个字段就能表示类型和值。但由于表示值可能需要多个字节,因此还需要一个指出 “要用多少字节表示值” 的长度字段。因此 ASN.1 把所有的数据元素都表示为 T-L-V 三个字段组成的序列(见图 6-22)。T 字段 (Tag) 定义数据的类型,L 字段 (Length) 定义 V 字段的长度,而 V 字段 (Value) 定义数据的值。

(1) T 字段又叫作标记字段,占 1 字节。T 字段比较复杂,因为它要定义的数据类型较多。T 字段又再分为以下三个子字段:
- 类别(2 位)共四种:通用类 (00),即 ASN.1 定义的类型;应用类 (01),即 SMI 定义的类型;上下文类 (10),即上下文所定义的类型;专用类 (11),保留为特定厂商定义的类型。
- 格式(1 位)共两种,指出数据类型的种类:简单数据类型 (0),结构化数据类型 (1)。
- 编号(5 位)用来标志不同的数据类型。编号的范围一般为 0~30。当编号大于 30 时,T 字段就要扩展为多个字节(这种情况很少用到,可参考 ITU-T X.209,这里从略)。
表 6-5 是一些数据类型的 T 字段的编码。
表 6-5 几种数据类型的 T 字段编码
| 数据类型 | 类别 | 格式 | 编号 | T字段(二进制) | T字段(十六进制) |
| INTEGER | 00 | 0 | 00010 | 00000010 | 02 |
| OCTET STRING | 00 | 0 | 00100 | 00000100 | 04 |
| OBJECT IDENTIFIER | 00 | 0 | 00110 | 00000110 | 06 |
| NULL | 00 | 0 | 00101 | 00000101 | 05 |
| Sequence, sequence of | 00 | 1 | 10000 | 00110000 | 30 |
| IPAddress | 01 | 0 | 00000 | 01000000 | 40 |
| Counter | 01 | 0 | 00001 | 01000001 | 41 |
| Gauge | 01 | 0 | 00010 | 01000010 | 42 |
| TimeTicks | 01 | 0 | 00011 | 01000011 | 43 |
| Opaque | 01 | 0 | 00100 | 01000100 | 44 |
(2) L 字段又叫作长度字段(单字节或多字节)。当 L 字段为单字节时,其最高位为 0,后面的 7 位定义 V 字段的长度。当 L 字段为多个字节时,其最高位为 1,而后面的 7 位定义后续字节的字节数(用二进制整数表示)。这时,所有的后续字节并置起来的二进制整数定义 V 字段的长度。图 6-23 给出了 L 字段的格式举例。

(3) V 字段又叫作值字段,用于定义数据元素的值。
根据以上所述,我们给出两个用十六进制表示的编码例子。例如,INTEGER 15,根据表 6-5,其 T 字段是 02,再根据表 6-4,INTEGER 类型要用 4 字节编码。最后得出 TLV 编码为 02 04 00 00 00 0F。又如 IPAddress 192.1.2.3,IPAddress 的 T 字段是 40,V 字段需要 4 字节表示,因此 IPAddress 192.1.2.3 的 TLV 编码是 40 04 C0 01 02 03。
TLV 方法中的 V 字段还可嵌套其他数据元素的 TLV 字段,并可多重嵌套。
6.7.3 管理信息库 MIB¶
所谓 “管理信息” 就是指在互联网的网管框架中被管对象的集合。被管对象必须维持可供管理程序读写的若干控制和状态信息。这些被管对象构成了一个虚拟的信息存储器,所以才称为管理信息库 MIB。管理程序就使用 MIB 中这些信息的值对网络进行管理(如读取或重新设置这些值)。只有在 MIB 中的对象才是 SNMP 所能够管理的。例如,路由器应当维持各网络接口的状态、入分组和出分组的流量、丢弃的分组和有差错的报文的统计信息,而调制解调器则应当维持发送和接收的字符数、码元传输速率和接受的呼叫等统计信息。因此在 MIB 中就必须有上面这样一些信息。
我们再看一下图 6-21,可以找到节点 mib-2 下面的部分是 MIB 子树。表 6-6 给出了节点 mib-2 所包含的前八个信息类别代表的意思(在后面还有好几个类别)。
表 6-6 节点 mib-2 所包含的信息类别举例
| 类别 | 标号 | 所包含的信息 |
| system | (1) | 主机或路由器的操作系统 |
| interfaces | (2) | 各种网络接口 |
| address translation | (3) | 地址转换(例如,ARP映射) |
| ip | (4) | IP软件 |
| icmp | (5) | ICMP软件 |
| tcp | (6) | TCP软件 |
| udp | (7) | UDP软件 |
| egp | (8) | EGP软件 |
我们可以用个简单例子进一步说明 MIB 的意义。例如,从图 6-21 可以看出,对象 ip 的标号是 4。因此,所有与 IP 有关的对象都从前缀 1.3.6.1.2.1.4 开始。
上面所说的 MIB 对象命名树的大小并没有限制。下面给出若干 MIB 变量的例子(见表 6-7),以便更好地理解 MIB 的意义。这里的 “变量” 是指特定对象的一个实例。
表 6-7 MIB 变量的例子
| MIB 变量 | 所属类别 | 意义 |
| sysUpTime | system | 距上次重启动的时间 |
| ifNumber | interfaces | 网络接口数 |
| ifMtu | interfaces | 特定接口的最大传送单元 MTU |
| ipDefaultTTL | ip | IP 在生存时间字段中使用的值 |
| ipInReceives | ip | 接收到的数据报数目 |
| ipForwDatagrams | ip | 转发的数据报数目 |
| ipOutNoRoutes | ip | 路由选择失败的数目 |
| ipReasmOKs | ip | 重装的数据报数目 |
| ipFragOKs | ip | 分片的数据报数目 |
| ipRoutingTable | ip | IP 路由表 |
| icmpInEchos | icmp | 收到的 ICMP 回送请求数目 |
| tcpRtoMin | tcp | TCP 允许的最小重传时间 |
| tcpMaxConn | tcp | 允许的最大 TCP 连接数目 |
| tcpInSegs | tcp | 已收到的 TCP 报文段数目 |
| udpInDatagrams | udp | 已收到的 UDP 数据报数目 |
上面列举的大多数项目的值可用一个整数来表示。但 MIB 也定义了更复杂的结构。例如,MIB 变量 ipRoutingTable 则定义一个完整的路由表。还有其他一些 MIB 变量定义了路由表项目的内容,并允许网络管理协议访问路由器中的单个项目,包括前缀、地址掩码以及下一跳地址等。当然,MIB 变量只给出了每个数据项的逻辑定义,而一个路由器使用的内部数据结构可能与 MIB 的定义不同。当一个查询到达路由器时,路由器上的代理软件负责 MIB 变量和路由器用于存储信息的数据结构之间的映射。
6.7.4 SNMP 的协议数据单元和报文¶
实际上,SNMP 的操作只有两种基本的管理功能,即:
(1) “读” 操作,用 Get 报文来检测各被管对象的状况;
(2) “写” 操作,用 Set 报文来改变各被管对象的状况。
SNMP 的这些功能通过探询操作来实现,即 SNMP 管理进程定时向被管理设备周期性地发送探询信息。上述时间间隔可通过 SNMP 的管理信息库 MIB 来建立。探询的好处是:第一,可使系统相对简单;第二,能限制通过网络所产生的管理信息的通信量。但探询管理协议不够灵活,而且所能管理的设备数目不能太多。探询系统的开销也较大。如探询频繁而并未得到有用的报告,则通信线路和计算机的 CPU 周期就被浪费了。
但 SNMP 不是完全的探询协议,它允许不经过询问就能发送某些信息。这种信息称为陷阱 (trap),表示它能够捕捉 “事件”。但这种陷阱信息的参数是受限制的。
当被管对象的代理检测到有事件发生时,就检查其门限值。代理只向管理进程报告达到某些门限值的事件(这就叫作过滤)。这种方法的好处是:第一,仅在严重事件发生时才发送陷阱;第二,陷阱信息很简单且所需字节数很少。
总之,使用探询(至少是周期性地)以维持对网络资源的实时监视,同时也采用陷阱机制报告特殊事件,使得 SNMP 成为一种有效的网络管理协议。
SNMP 使用无连接的 UDP,因此在网络上传送 SNMP 报文的开销较小。但 UDP 是不保证可靠交付的。这里还要指出,SNMP 使用 UDP 的方法有些特殊。在运行代理程序的服务器端用熟知端口 161 来接收 Get 或 Set 报文和发送响应报文(与熟知端口通信的客户端使用临时端口),但运行管理程序的客户端则使用熟知端口 162 来接收来自各代理的 trap 报文。
SNMP 现在共定义了如表 6-8 所示的 8 种类型的协议数据单元 [RFC 3416, STD62],其中 PDU 编号为 4 的已经废弃了。在 PDU 编号后面是对应的 T 字段值(十六进制形式表示)。
表 6-8 SNMP 定义的协议数据单元类型
| PDU 编号(T 字段) | PDU 名称 | 用途 |
| 0(A0) | GetRequest | 管理者从代理读取一个或一组变量的值 |
| 1(A1) | GetNextRequest | 管理者从代理读取MIB树上的下一个变量的值(即使不知道此变量名也行)。此操作可反复进行,特别是按顺序一一读取列表中的值很方便 |
| 2(A2) | Response | 代理向管理者或管理者向管理者发送对五种Request报文的响应,并提供差错码、差错状态等信息 |
| 3(A3) | SetRequest | 管理者对代理的一个或多个MIB变量的值进行设置 |
| 5(A5) | GetBulkRequest | 管理者从代理读取大数据块的值(如大的列表中的值) |
| 6(A6) | InformRequest | 管理者从另一远程管理者读取该管理者控制的代理中的变量值 |
| 7(A7) | SNMPv2Trap | 代理向管理者报告代理中发生的异常事件 |
| 8(A8) | Report | 在管理者之间报告某些类型的差错,目前尚未定义 |
和大多数 TCP/IP 协议不一样,SNMP 报文没有固定的字段。相反,它们使用标准 ASN.1 编码。因此,SNMP 报文用人工进行编码和理解时都比较困难。为此,在图 6-24 中给出了 SNMPv1 的报文格式。可以看出,一个 SNMP 报文共由四个部分组成,即版本、首部、安全参数和 SNMP 报文的数据部分。目前最新版本是版本 3。首部包括报文标识 (message identification)、最大报文长度、报文标志 (message flag)。报文标志占 1 字节,其中的每一位定义安全类型或其他信息。安全参数用来产生报文摘要(见下一章的 7.3.1 节)。

从图 6-24 可看出,在 SNMP PDU 前面还有两个有关加密信息的字段。这是当数据部分需要加密时才使用的两个字段。与网络管理直接相关的是后面的 SNMP PDU 部分。对于表 6-8 给出的前四种 PDU 的格式都是相同的,即由 PDU 类型、请求 ID、差错状态、差错索引以及变量绑定这几个字段组成。PDU 的各种类型以及类型的编号和 T 字段的编码已在表 6-8 中给出。下面简单介绍一下其他字段的作用。
为了大致了解 ASN.1 给出的定义的形式,下面举出定义 GetRequest-PDU 的例子。两个连字符 “--” 后面的是注解。
但变量 VarBindList 是什么类型呢?还需要继续定义(这里从略)。上面 ASN.1 定义中的第二行中的 IMPLICIT 叫作隐式标记,是为了在进行编码时可省去对 IMPLICIT 后面的类型 (SEQUENCE) 的编码,使最后得出的编码更加简洁。
下面我们假定管理者发送 GetRequest-PDU,为的是从某路由器的代理进程获得 “收到 UDP 数据报的数目” 的信息。从图 6-21 可以查出,mib-2 下面第 7 个节点是 udp,而 udp 节点下面的第一个节点就是 udpInDatagrams。由于这个节点已经是叶节点(即没有连接在它下面的子节点了),读取这个节点的数值时应在节点标识符后面加上 0,即 1.3.1.1.2.1.7.1.0。这样,可得出 GetRequest-PDU 的 ASN.1 编码,如图 6-25 所示。

可以把图中各字段的十六进制编码表示如下。
6.8 应用进程跨越网络的通信¶
在这以前我们已经讨论了互联网使用的几种常用的应用层协议,这些应用协议使广大用户可以更加方便地利用互联网的资源。
现在的问题是:如果我们还有一些特定的应用需要互联网的支持,但这些应用又不能直接使用已经标准化的互联网应用协议,那么我们应当做哪些工作?要回答这个问题,实际上就是要了解下面要介绍的系统调用和应用编程接口。这些问题需要一门专门的课程来学习,我们在这里只能给出一些初步的概念。
6.8.1 系统调用和应用编程接口¶
大多数操作系统使用系统调用 (system call) 的机制在应用程序和操作系统之间传递控制权。对程序员来说,系统调用和一般程序设计中的函数调用非常相似,只是系统调用是将控制权传递给了操作系统。图 6-26 说明了多个应用进程使用系统调用的机制。

当某个应用进程启动系统调用时,控制权就从应用进程传递给了系统调用接口。此接口再把控制权传递给计算机的操作系统。操作系统把这个调用转给某个内部过程,并执行所请求的操作。内部过程一旦执行完毕,控制权就又通过系统调用接口返回给应用进程。总之,只要应用进程需要从操作系统获得服务,就要把控制权传递给操作系统,操作系统在执行必要的操作后把控制权返还给应用进程。因此,系统调用接口实际上就是应用进程的控制权和操作系统的控制权进行转换的一个接口。由于应用程序在使用系统调用之前要编写一些程序,特别是需要设置系统调用中的许多参数,因此这种系统调用接口又称为应用编程接口 API (Application Programming Interface)。API 从程序设计的角度定义了许多标准的系统调用函数。应用进程只要使用标准的系统调用函数就可得到操作系统的服务。因此从程序设计的角度看,也可以把 API 看成是应用程序和操作系统之间的接口。
现在 TCP/IP 协议软件已驻留在操作系统中。由于 TCP/IP 协议族被设计成能运行在多种操作系统的环境中,因此 TCP/IP 标准没有规定应用程序与 TCP/IP 协议软件如何接口的细节,而是允许系统设计者能够选择有关 API 的具体实现细节。目前,只有几种可供应用程序使用 TCP/IP 的应用编程接口 API。这里最著名的就是美国加利福尼亚大学伯克利分校为 Berkeley UNIX 操作系统定义的一种 API,它又称为套接字接口 (socket interface)(或插口接口)。微软公司在其操作系统中采用了套接字接口 API,形成了一个稍有不同的 API,并称之为 Windows Socket,简称为 WinSock。AT&T 为其 UNIX 系统 V 定义了一种 API,简写为 TLI (Transport Layer Interface)。
我们知道,若要让计算机做某件事情,就要编写使计算机能理解的程序。在网络环境下的计算机应用都有一个共同特点,这就是:位于不同地点的计算机要通过网络进行通信。从另一种角度看,计算机之间的通信就是本计算机要读取另一个地点的计算机中的数据,或者要把数据从本计算机写入到另一个地点的计算机中。这种 “读取” 和 “写入” 的过程都要用到上面所说的系统调用。
在讨论网络编程时常常把套接字作为应用进程和运输层协议之间的接口,图 6-27 表示这一概念。图中假定了运输层使用 TCP 协议(若使用 UDP 协议,情况也是类似的,只是 UDP 是无连接的。通信的两端仍然可用两个套接字来标志)。现在套接字已成为计算机操作系统内核的一部分。

请注意:在套接字以上的进程是受应用程序控制的,而在套接字以下的运输层协议软件则是受计算机操作系统的控制。因此,只要应用程序使用 TCP/IP 协议进行通信,它就必须通过套接字与操作系统交互(这就要使用系统调用函数)并请求其服务。我们应当注意到,应用程序的开发者对套接字以上的应用进程具有完全的控制,但对套接字以下的运输层却只有很少的控制,例如,可以选择运输层协议(TCP 或 UDP)以及一些运输层的参数(如最大缓存空间和最大报文长度等)。
当应用进程(客户或服务器)需要使用网络进行通信时,必须首先发出 socket 系统调用,请求操作系统为其创建一个 “套接字”。这个调用的实际效果是请求操作系统把网络通信所需要的一些系统资源(存储器空间、CPU 时间、网络带宽等)分配给该应用进程。操作系统为这些资源的总和用一个叫作套接字描述符 (socket descriptor) 的号码(小的整数)来表示,然后把这个套接字描述符返回给应用进程。此后,应用进程所进行的网络操作(建立连接、收发数据、调整网络通信参数等)都必须使用这个套接字描述符。所以,几乎所有的网络系统调用都把这个套接字描述符作为套接字的许多参数中的第一个参数。在处理系统调用的时候,通过套接字描述符,操作系统就可以识别出应该使用哪些资源来完成应用进程所请求的服务。通信完毕后,应用进程通过一个关闭套接字的 close 系统调用通知操作系统回收与该套接字描述符相关的所有资源。由此可见,套接字是应用进程为了获得网络通信服务而与操作系统进行交互时使用的一种机制。
图 6-28 给出了当应用进程发出 socket 系统调用时,操作系统所创建的套接字描述符与套接字数据结构的关系。由于在一个进程中可能同时出现多个套接字,因此需要有一个存放套接字描述符的表,而每一个套接字描述符有一个指针指向存放套接字的地址。在套接字的数据结构中有许多参数要填写。图 6-28 中已填写好的参数是协议族(PF_INET,表示使用 Internet 的 TCP/IP 协议族)和服务(SOCK_STREAM,表示使用流式服务,也就是使用 TCP 服务)。在刚刚创建一个新的套接字时,有灰色背景的四个项目(本地和远地 IP 地址,本地和远地端口)都是未填写的,因此它和任何机器中的应用进程暂时都还没有联系。

这里要特别强调一下,在第 5 章 5.3.2 节的最后,我们曾指出,同一个名词 socket 可表示多种不同的意思。在本节讨论 socket 系统调用时,套接字 socket 已不仅仅是 RFC793 所定义的如公式 (5-1) 所示的那样,而是如图 6-28 右边所示的套接字的数据结构。
6.8.2 几种常用的系统调用¶
下面我们以使用 TCP 的服务为例介绍几种常用的系统调用。
1. 连接建立阶段¶
当套接字被创建后,它的端口号和 IP 地址都是空的,因此应用进程要调用 bind(绑定)来指明套接字的本地地址(本地端口号和本地 IP 地址)。在服务器端调用 bind 时就是把熟知端口号和本地 IP 地址填写到已创建的套接字中。这就叫作把本地地址绑定到套接字。在客户端也可以不调用 bind,这时由操作系统内核自动分配一个动态端口号(通信结束后由系统收回)。
服务器在调用 bind 后,还必须调用 listen(收听)把套接字设置为被动方式,以便随时接受客户的服务请求。UDP 服务器由于只提供无连接服务,不使用 listen 系统调用。
服务器紧接着就调用 accept(接受),以便把远地客户进程发来的连接请求提取出来。系统调用 accept 的一个变量就是要指明是从哪一个套接字发起的连接。
调用 accept 要完成的动作较多。这是因为一个服务器必须能够同时处理多个连接。这样的服务器常称为并发方式 (concurrent) 工作的服务器。可以有多种方法实现这种并发方式。图 6-29 所示的是一种实现方法。
主服务器进程 M(就是通常所说的服务器进程)一调用 accept,就为每一个新的连接请求创建一个新的套接字,并把这个新创建的套接字的标识符返回给发起连接的客户方。与此同时,主服务器进程还要创建一个从属服务器进程(如图 6-29 中的 \(S_{1}\) )来处理新建立的连接。这样,从属服务器进程用这个新创建的套接字和客户进程建立连接,而主服务器进程用原来的套接字重新调用 accept,继续接受下一个连接请求。在已建立的连接上,从属服务器进程就使用这个新创建的套接字传送和接收数据。数据通信结束后,从属服务器进程就关闭这个新创建的套接字,同时这个从属服务器也被撤销。

总之,在任一时刻,服务器中总是有一个主服务器进程和零个或多个从属服务器进程。主服务器进程用原来的套接字接受连接请求,而从属服务器进程用新创建的套接字(在图 6-29 中注明是 “连接套接字”)和相应的客户建立连接并可进行双向传送数据。
以上介绍的是服务器为了接受客户端发起的连接请求而进行的一些系统调用。现在看一下客户端的情况。当使用 TCP 协议的客户已经调用 socket 创建了套接字后,客户进程就调用 connect,以便和远地服务器建立连接(这就是主动打开,相当于客户发出的连接请求)。在 connect 系统调用中,客户必须指明远地端点(即远地服务器的 IP 地址和端口号)。
2. 数据传送阶段¶
客户和服务器都在 TCP 连接上使用 send 系统调用传送数据,使用 recv 系统调用接收数据。通常客户使用 send 发送请求,而服务器使用 send 发送回答。服务器使用 recv 接收客户用 send 调用发送的请求。客户在发完请求后用 recv 接收回答。
调用 send 需要三个变量:数据要发往的套接字的描述符、要发送的数据的地址以及数据的长度。通常 send 调用把数据复制到操作系统内核的缓存中。若系统的缓存已满,send 就暂时阻塞,直到缓存有空间存放新的数据。
调用 recv 也需要三个变量:要使用的套接字的描述符、缓存的地址以及缓存空间的长度。
3. 连接释放阶段¶
一旦客户或服务器结束使用套接字,就把套接字撤销。这时就调用 close 释放连接和撤销套接字。
图 6-30 画出了上述的一些系统调用的使用顺序。有些系统调用在一个 TCP 连接中可能会循环使用。

UDP 服务器由于只提供无连接服务,因此不使用 listen 和 accept 系统调用。
6.9 P2P 应用¶
我们在第 1 章的 1.3.1 节中已经简单地介绍了 P2P 应用的概念。现在我们将进一步讨论 P2P 应用的若干工作原理。
P2P 应用就是指具有 P2P 体系结构的网络应用。所谓 P2P 体系结构就是在这样的网络应用中,没有(或只有极少数的)固定的服务器,而绝大多数的交互都是使用对等方式(P2P 方式)进行的。
P2P 应用的范围很广,例如,文件分发、实时音频或视频会议、数据库系统、网络服务支持(如 P2P 打车软件、P2P 理财等)。限于篇幅,下面只介绍最常用的 P2P 文件分发的工作原理。
P2P 文件分发不需要使用集中式的媒体服务器,而所有的音频 / 视频文件都是在普通的互联网用户之间传输的。这其实是相当于有很多(有时达到上百万个)分散在各地的媒体服务器(由普通用户的计算机充当这种媒体服务器)向其他用户提供所要下载的音频 / 视频文件。这种 P2P 文件分发方式解决了集中式媒体服务器可能出现的瓶颈问题。
目前在互联网流量中,P2P 工作方式下的文件分发已占据了最大的份额,比万维网应用所占的比例大得多。因此单纯从流量的角度看,P2P 文件分发应当是互联网上最重要的应用。现在 P2P 文件分发不仅传送音频文件 MP3,而且还传送视频文件(10~1000 MB,或更大)、各种软件和图像文件。
6.9.1 具有集中目录服务器的 P2P 工作方式¶
最早使用 P2P 工作方式的是 Napster。这个名称来自 1999 年美国东北大学的新生 Shawn Fanning 所写的一个叫作 Napster 的软件。利用这个软件就可通过互联网免费下载各种 MP3 音乐。Napster 的出现使 MP3 成为网络音乐事实上的标准 \(^{①}\) 。
Napster 能够搜索音乐文件,能够提供检索功能。所有音乐文件的索引信息都集中存放在 Napster 目录服务器中。这个目录服务器起着索引的作用。使用者只要查找目录服务器,就可知道应从何处下载所要的 MP3 文件。在 2000 年,Napster 成为互联网上最流行的 P2P 应用,并占据互联网上的通信量中相当大的比例。
这里的关键就是运行 Napster 的所有用户,都必须及时向 Napster 的目录服务器报告自己已经存有哪些音乐文件。Napster 目录服务器就用这些用户信息建立起一个动态数据库,集中存储了所有用户的音乐文件信息(即对象名和相应的 IP 地址)。当某个用户想下载某个 MP3 文件时,就向目录服务器发出查询(这个过程仍是传统的客户 - 服务器方式),目录服务器检索出结果后向用户返回存放这一文件的计算机 IP 地址,于是这个用户就可以从中选取一个地址下载想要得到的 MP3 文件(这个下载过程就是 P2P 方式)。可以看出,Napster 的文件传输是分散的(P2P 方式),但文件的定位则是集中的(客户 - 服务器方式)。
图 6-31 是 Napster 的工作过程的示意图。假定 Napster 目录服务器已经建立了其用户的动态数据库。图中给出了某个用户要下载音乐文件的主要交互过程。

这种集中式目录服务器的最大缺点就是可靠性差,而且会成为其性能的瓶颈(尤其是在用户数非常多的情况下)。更为严重的是这种做法侵犯了唱片公司的版权。虽然 Napster 网站并没有直接非法复制任何 MP3 文件(Napster 网站不存储任何 MP3 文件,因而并没有直接侵犯版权),但法院还是判决 Napster 属于 “间接侵害版权”,因此在 2000 年 7 月底 Napster 网站就被迫关闭了。
6.9.2 具有全分布式结构的 P2P 文件共享程序¶
在第一代 P2P 文件共享网站 Napster 关闭后,开始出现了以 Gnutella 为代表的第二代 P2P 文件共享程序。Gnutella 是一种采用全分布方法定位内容的 P2P 文件共享应用程序。Gnutella 与 Napster 最大的区别就是不使用集中式的目录服务器进行查询,而是使用洪泛法在大量 Gnutella 用户之间进行查询。为了不使查询的通信量过大,Gnutella 设计了一种有限范围的洪泛查询。这样可以减少倾注到互联网的查询流量,但由于查询的范围受限,因而这也影响到查询定位的准确性。
为了更加有效地在大量用户之间使用 P2P 技术下载共享文件,最近几年已经开发出很多种第三代 P2P 共享文件程序 [KURO17],它们使用分散定位和分散传输技术。如 KaZaA,电骤 eMule,比特洪流 BT (Bit Torrent) 等。
下面对比特洪流 BT 的主要特点进行简单的介绍。
在 P2P 的文件分发应用中,2001 年由 Brahm Cohen 开发的 BitTorrent(中文意思是 “比特洪流”)是很具代表性的一个。取这个名称的原因就是 BitTorrent 把参与某个文件分发的所有对等方的集合称为一个洪流 (torrent)。为了方便,下面我们使用 BitTorrent 的简称 BT。BT 把对等方下载文件的数据单元称为文件块 (chunk),一个文件块的长度是固定不变的,例如,典型的数值是 256 KB。当一个新的对等方加入某个洪流时,一开始它并没有文件块。但新的对等方逐渐地能够下载到一些文件块。而与此同时,它也为别的对等方上传一些文件块。某个对等方获得了整个的文件后,可以立即退出这个洪流(相当于自私的用户),也可继续留在这个洪流中,为其他的对等方上传文件块(相当于无私的用户)。加入或退出某个洪流可在任何时间完成(即使在某个文件还没有下载完毕时),也是完全自由的。
BT 的协议相当复杂 [W-BT]。下面讨论其基本机制。
每一个洪流都有一个基础设施节点,叫作追踪器 (tracker)。当一个对等方加入洪流时,必须向追踪器登记(或称为注册),并周期性地通知追踪器它仍在洪流中。追踪器因而就跟踪了洪流中的对等方。一个洪流中可以拥有少到几个多到几百或几千个对等方。
我们用图 6-32 来进一步说明 BT 的工作原理。当一个新的对等方 A 加入洪流时,追踪器就随机地从参与的对等方集合中选择若干个(例如,30 个),并把这些对等方的 IP 地址告诉 A。于是 A 就和这些对等方建立了 TCP 连接。我们称所有与 A 建立了 TCP 连接的对等方为 “相邻对等方” (neighboring peers)。在图 6-32 中我们在上面的覆盖网络中画出了 A 有三个相邻对等方(B, C 和 D)。这些相邻对等方的数目是动态变化的,有的对等方可能不久就离开了,但不久后又有新加入进来的对等方。请注意,实际的网络拓扑可能是非常复杂的(参见图 6-32 覆盖网络下面的实际网络图)。我们知道,TCP 连接只是个逻辑连接,而每一个 TCP 连接可能会穿越很多的网络。因此我们在讨论问题时,可以利用实际网络上面的一个更加简洁的覆盖网络,这个覆盖网络忽略了实际网络的许多细节,使问题的讨论更加方便。在覆盖网络中,A 的三个相邻对等方就看得很清楚。
在任何时刻,每一个对等方可能只拥有某文件的一个文件块子集,而不同的对等方所拥有的文件块子集也不会完全相同。对等方 A 将通过 TCP 连接周期性地向其相邻对等方索取它们拥有的文件块列表。根据收到的文件块列表,A 就知道了应当请求哪一个相邻对等方
把哪些自己缺少的文件块发送过来。

图 6-33 是对等方之间互相传送数据块的示意图。例如,A 向 B、C 和 D 索取数据块,但 B 同时也向 C 和 D 传送数据块,D 和 C 还互相传送数据块。由于 P2P 对等用户的数量非常多,因此,从不同的对等方获得不同的数据块,然后组装成整个的文件,一般要比仅从一个地方下载整个的文件要快很多。

然而 A 必须做出两个重要决定。第一,哪些文件块是首先需要向其相邻对等方请求的?第二,在很多向 A 请求文件块的相邻对等方中,A 应当向哪些相邻对等方发送所请求的文件块?
对于第一个问题,A 要使用叫作最稀有的优先 (rarest first) 的技术。我们知道,凡是 A 所缺少的而正好相邻对等方已拥有的文件块,都应当去索取。可能其中的某些文件块,很多相邻对等方都有(即文件块的副本很多),这就是 “不稀有的” 文件块,以后可慢慢请求。如果 A 所缺少的文件块在相邻对等方中的副本很少,那就是 “很稀有的”。因此,A 首先应当请求副本最少的文件块(即最稀有的)。否则,一旦拥有最稀有文件块的对等方退出了洪流,就会影响 A 对所缺文件块的收集。
对于第二个问题,BT 采用了一种更加机灵的算法,其基本思想就是:凡当前有以最高数据率向 A 传送文件块的某相邻对等方,A 就优先把所请求的文件块传送给该相邻对等方。具体来说,A 持续地测量从其相邻对等方接收数据的速率,并确定速率最高的 4 个相邻对等方。接着,A 就把文件块发送给这 4 个相邻对等方。每隔 10 秒钟,A 还要重新计算数据率,然后可能修改这 4 个对等方。在 BT 的术语中,这 4 个对等方叫作已疏通的或无障碍的 (unchoked) 对等方。更重要的是,每隔 30 秒,A 要随机地找一个另外的相邻对等方 B,并向其发送文件块。这样,A 有可能成为 B 的前 4 位上传文件块的提供者。在此情况下,B 也有可能向 A 发送文件块。如果 B 发送文件块的速率足够快,那么 B 也有可能进入 A 的前 4 位上传文件块的提供者。这样做的结果是,这些对等方相互之间都能够以令人满意的速率交换文件块。
6.9.3 P2P 文件分发的分析¶
我们从一个例子开始,来讨论 P2P 文件分发中的几个重要概念 [KURO17]。
在图 6-34 中,有 N 台主机要从互联网上的服务器下载一个大文件,其长度为 F bit。在图中我们把这个文件也记为 F。按照习惯,从互联网传送数据到主机,叫作下载 (download),而反过来传送数据,即从主机向互联网传送,则称为上传 (upload) 或上载。服务器的文件是供互联网上的用户享用的,因此服务器的文件只是单方向上传到互联网。我们把服务器的上传速率记为 \(u_{s}\) ,单位是 bit/s。再假定主机与互联网连接的链路的上传速率和下载速率分别为 \(u_{i}\) 和 \(d_{i}\) ,单位都是 bit/s。我们还假定互联网的核心部分不会产生拥塞。瓶颈只会发生在服务器的接入链路,或者是某些主机的接入链路。

我们先在传统的客户 - 服务器方式下,计算给所有主机分发完毕的最短时间 \(T_{\mathrm{cs}}\) 。
从服务器端考虑,N 台主机共需要从服务器得到的数据总量(比特数)是 NF。如果服务器能够不停地以其上传速率 \(u_{s}\) 向各主机传送数据,一直到各主机都收到文件 F,就需要时间 \(NF/u_{s}\) ,单位是秒。由此可见, \(T_{cs}\) 不可能小于 \(NF/u_{s}\) 。
如果 N 台主机都以各自的下载速率不停地下载文件 F,那么下载速率最慢的主机(设其下载速率为 \(d_{min}\) )的下载文件时间 \((F/d_{\min})\) ,将是 N 个下载时间中最大的一个。由此可见, \(T_{cs}\) 也不可能小于 \(F/d_{min}\) 。
如果 \(NF/u_{s} \geqslant F/d_{min}\) ,则瓶颈在服务器端的接入链路。这时 \(T_{cs} = NF/u_{s}\) 。
如果 \(F / d_{\mathrm{min}}\geqslant NF / u_{\mathrm{s}}\) ,则瓶颈在下载最慢的主机的接入链路。这时 \(T_{\mathrm{cs}} = F / d_{\mathrm{min}}\)
由此可得出所有主机都下载完文件 \(F\) 的最少时间是
从以上分析可以看出,若公式 (6-2) 括号中的第一项大于第二项,则 \(T_{cs}\) 就与主机数 N 成正比。如果主机数增大 1000 倍,那么文件的分发时间也要增大 1000 倍。
下面讨论在 P2P 方式下,文件全部分发完毕的最少时间 \(T_{P2P}\) 。然而在 P2P 方式下,文件分发所需的时间较难计算,这是因为每一台主机在接收文件的同时,还利用自己的上传能力向其他主机传送文件。文件传送所需的时间取决于主机向对等方传送文件的具体方式。但是,我们还是可以导出文件分发所需的最少时间的表达式。
在文件分发开始时,只有服务器有文件 F。服务器必须把文件 F 的每一个比特通过接入链路传送到互联网(至少要传送一次)。因此文件分发的最少时间不可能小于 \(F/u_{s}\) 。和客户 - 服务器方式相比,在 P2P 方式下,服务器不需要一遍一遍地发送文件 F,因为互联网上的其他主机(即对等方)可以代替服务器向其他对等方分发文件 F。
在 P2P 方式下,下载速率最慢的主机(设其下载速率为 \(d_{min}\) )下载文件 F 的时间是 \(F/d_{min}\) ,这是 N 个对等方下载时间中最大的一个。可见文件分发的最少时间不可能小于 \(F/d_{min}\) 。这个结论和客户 - 服务器方式是一样的。
整个系统中所有主机(包括服务器)的上传速率之和是 \(u_{T}=u_{s}+u_{1}+u_{2}+\ldots+u_{N}\) 。因此,文件分发的最少时间也不可能小于 \(NF/u_{T}\) 。
这样,我们得出在 P2P 方式下所有主机都下载完文件 \(F\) 的最少时间的下限是
在公式 (6-3) 的推导过程中,我们假定每一个对等方只要收到一个比特就立即上传到互联网的其他对等方。但实际上是把收到的若干个比特组成一个数据块后再上传出去。但是当文件 F 很大时,我们也可以在公式 (6-3) 中取等号,作为文件 F 的最少分发时间 \(T_{P2P}\) 的近似值。
有一种情况最值得我们注意。这就是对等方的数目 N 非常大,因此在公式 (6-3) 的括号中的最后一项的值将大于前两项的值。这样, \(T_{P2P}\) 值的下限就近似为 \(NF/u_{T}\) 。
我们再假定一些数据。设所有的对等方的上传速率都是 \(u\) ,并且 \(F / u = 1\) 小时,所有对等方的下载速率都不小于服务器的上传速率,因而不会对我们的计算产生影响。我们再设服务器的上传速率 \(u_{\mathrm{s}} = 10u\) 。当 \(N = 30\) 时,用公式 (6-3) 算出所有主机都下载完文件 \(F\) 的最少时间的下限是 \(T_{\mathrm{P2P}} = 0.75 F / u = 0.75\) 小时(这个数值一定小于 1 小时)。如果采用客户 - 服务器方式,则当 \(N = 30\) 时,所有主机都下载完文件 \(F\) 的最少时间是 \(T_{\mathrm{cs}} = NF / u_{\mathrm{s}} = 3\) 小时。
6.9.4 在 P2P 对等方中搜索对象¶
在 P2P 文件系统中,对等方用户的数量非常多,并且处于一种无序的状态。任何一个对等方可以随时加入进来或随时退出。在这种情况下,怎样有效地找到所需的文件,也就是怎样有效地定位对等方及其资源,乃是 P2P 系统中的一个十分重要的问题。
限于篇幅,我们在这里只简单介绍一下怎样利用散列函数来定位对等方。
我们知道,Gnutella 是一种采用全分布方法定位内容的 P2P 文件共享应用程序,它解决了集中式目录服务器所造成的瓶颈问题。然而 Gnutella 是在非结构化的覆盖网络中采用查询洪泛的方法来进行查找的,因此查找的效率较低。现在比较好的查找方法是设法构建一种分布式数据库,以进行对等方及其资源的定位。这种分布式数据库在概念上并不复杂,只要能够支持大量对等方(可能有几百万个)进行索引查找即可。存储在数据库中的信息只有两个部分:
存放在数据库中的信息就是大量成对出现的(资源名 K,节点的 IP 地址 N)。在查找某资源名 K 时,只要在数据库中查找到匹配的资源名 K,数据库就能够返回对应的节点的 IP 地址 N。所以问题的关键就是要设法把每个资源名 K 存放在一个非常便于查找的地方。
细心的读者可能会联想到曾在前面 6.1 节讨论的 DNS 域名系统。DNS 是根据主机的域名来查找其 IP 地址,这和 P2P 的情况有相似之处。但我们知道,主机的域名是结构化的命名系统,因此域名服务器可以划分为几种不同的级别(如根服务器等)便于查找。但 P2P 系统则不同,其资源名是非结构化的。因此不能套用 DNS 的那种查找方法。
前面已经讲过,Napster 在一个集中式目录服务器中构建的查找数据库虽然很简单,但性能上却有瓶颈。在 P2P 系统中,应怎样构建分布式的 P2P 数据库?让每个对等方都拥有所有对等方 IP 地址的列表是不可行的。让所有成对出现的(资源名 K, IP 地址 N)随机地分散到各对等方也是不可行的。因为这将使查找对象的次数过大,无法使用。现在广泛使用的索引和查找技术叫作分布式散列表 DHT (Distributed Hash Table)。DHT 也可译为分布式哈希表,它是由大量对等方共同维护的散列表。基于 DHT 的具体算法已有不少,如 Chord, Pastry, CAN (Content Addressable Network),以及 Kademilia 等。下面简单介绍广泛使用的 Chord 算法,这是美国麻省理工大学于 2001 年提出的 [STOI01]。
分布式散列表 DHT 利用散列函数,把资源名 K 及其存放的节点 IP 地址 N 都分别映射为资源名标识符 KID 和节点标识符 NID。如果所有的对等方都使用散列函数 SHA-1(我们在下一章 7.3.1 节还要介绍 SHA-1 在网络安全方面的应用),那么通过散列得出的标识符 KID 和 NID 都是 160 位二进制数字,且其数值范围在 \([0, 2^{160} - 1]\) 之间。虽然从理论上讲,散列函数 SHA-1 是多对一的函数,但实际上不同输入得到相同的输出的概率是极小的。此外,通过 SHA-1 映射得到的标识符能够比较均匀而稀疏地分布在 Chord 环上。为便于讨论,我们假定现在标识符只有 5 位二进制数字,也就是说,所有经散列函数得出的标识符的数值范围都在 \([0, 31]\) 之间。Chord 把节点按标识符数值从小到大沿顺时针排列成一个环形覆盖网络(见图 6-35 (a)),并按照下面的规则进行映射:
请注意:在图 6-35 中,K31 和 K2 都放在 N4,这表示要查找存放资源 K31 或 K2 的节
点的 IP 地址,就应当到节点 N4 去查找。请注意,资源 K31 和 K2 并非存放在节点 N4。
这就是说,每个资源由 Chord 环上与其标识符值最接近的下一个节点提供服务。我们再强调一下,Chord 环并非实际的网络。在 Chord 环上相邻的节点,在地理上很可能相距非常远。


Chord 环上的每一个节点都要维护两个指针变量,一个指向其后继节点,而另一个指向其前任节点。例如,在图 6-35 (a) 中,N10 的后继节点是 N20(N10 沿顺时针方向的下一个节点),其前任节点是 N7(N10 沿逆时针方向的前一个节点)。如果一个新的节点 N13 加入进来,那么 N20 的前任节点就变为 N13,因而 K12 就要从 N20 的位置移到 N13,同时 N10 的后继节点就变为 N13(见图 6-35 (b))。此外,如果节点 N26 退出,那么 K23 就要移到 N30,而 N30 的前任节点就变为 N20,同时 N20 的后继节点变为 N30。
在这样的 Chord 环上查找资源,从理论上讲,任何一个节点,只要从其后继节点一个个地遍历查找下去,一定可以找到所查询的资源。可见要定位一个资源,平均需要沿环发送查找报文 N/2 个,或遍历 \(O(N)\) 个节点(N 为环上的总节点数)。显然,这种顺序查找的方法效率很低。
为了加速查找,在 Chord 环上可以增加一些指针表 (finger table),它又称为路由表或查找器表。若 Chord 环上的标识符有 m 位(现在 m = 5),则在节点 n 上的指针表可设置不超过 m 个指针,指向其后继的节点。我们先看图 6-36 中节点 N4 的指针表。指针表中的第 2 列是从 N4 可以指向的多个后继节点。本来每一个节点仅仅指向沿顺时针方向的下一个后继节点,但现在则指向多个后继节点(在本例中就是 N7, N10 和 N20)。第 1 列的第 i 行是计算 \((N4 + 2^{i-1})\) ,用来得出后继节点。例如,第 4 行 i = 4,算出 \((N4 + 2^{i-1}) = N4 + 8 = 12\) ,而 Chord 环上的节点 12 的后继节点是 N20。图中还画出了从 N4 到这几个后继节点的连线(这些连线就是 Chord 环上的弦,Chord 名字由此得出)。还有一点要注意的是,在 N20 的指针表中的第 5 行, \(N20 + 16 = 36\) ,但按照模 \(2^{5}\) 运算, \(36 \mod 2^{5} = 4\) ,恰好节点 4 的后继节点是 N4。
假定在图 6-36 中的节点 N4 要查找 K29。如果用遍历各节点的方法,则要查找 5 次,即 N7→N10→N20→N26→N30。但若利用指针表,则 N4 首先在自己的指针表中寻找在不到 29 且最接近 29 的节点,即 N20,然后把定位资源 K29 的请求发送给 N20。在 N20 的指针表中继续类似的寻找。结果是:最接近 29 的节点是 N30。这就是存放资源 K29 的节点。这种查找方法类似于二分查找,只用了两次查找,定位一个资源仅需 \(O(\log_{2}N)\) 步。

在 P2P 网络中,对等方可能相当频繁地加入或退出系统,这就需要很好地维护这个分布式数据库(维护各节点的指针和指针表),而这种维护的工作量可能会很大。当对等方数量非常大时,究竟采用何种查询机制更加合理,则需要根据具体情况来确定。
P2P 技术还在不断地改进,但随着 P2P 文件共享程序日益广泛地使用,也产生了一系列的问题有待于解决。这些问题已迫使人们要重新思考下一代互联网应如何演进。例如,音频 / 视频文件的知识产权就是其中的一个问题。又如,当非法盗版的、或不健康的音频 / 视频文件在互联网上利用 P2P 文件共享程序广泛传播时,要对 P2P 的流量进行有效的管理,在技术上还是有相当的难度。由于现在 P2P 文件共享程序的大量使用,已经消耗了互联网主干网上大部分的带宽。因此,怎样制定出合理的收费标准,既能够让广大网民接受,又能使网络运营商赢利并继续加大投入,也是目前迫切需要解决的问题。
本章的重要概念¶
的是数据连接。
- 万维网 WWW 是一个大规模的、联机式的信息储藏所,可以非常方便地从互联网上的一个站点链接到另一个站点。
- 万维网的客户程序向互联网中的服务器程序发出请求,服务器程序向客户程序送回客户所要的万维网文档。在客户程序主窗口上显示出的万维网文档称为页面。
- 万维网使用统一资源定位符 URL 来标志万维网上的各种文档,并使每一个文档在整个互联网的范围内具有唯一的标识符 URL。
- 万维网客户程序与服务器程序之间进行交互所使用的协议是超文本传送协议 HTTP。HTTP 使用 TCP 连接进行可靠的传送。但 HTTP 协议本身是无连接、无状态的。HTTP/1.1 协议使用了持续连接(分为非流水线方式和流水线方式)。
- HTTP/2 可使用同一个 TCP 连接把服务器发回的响应并行发回;允许客户复用 TCP 连接进行多个请求;把所有的报文划分为许多较小的二进制编码的帧,采用新的压缩算法,不发送重复的首部字段,大大减小了首部的开销,提高了传输效率。
- 万维网使用超文本标记语言 HTML 来显示各种万维网页面。
- 万维网静态文档是指在文档创作完毕后就存放在万维网服务器中,在被用户浏览的过程中,内容不会改变。动态文档是指文档的内容是在浏览器访问万维网服务器时才由应用程序动态创建的。
- 活动文档技术可以使浏览器屏幕连续更新。活动文档程序可与用户直接交互,并可连续地改变屏幕的显示。
- 在万维网中用来进行搜索的工具叫作搜索引擎。搜索引擎大体上可划分为全文检索搜索引擎和分类目录搜索引擎两大类。
- 电子邮件是互联网上使用最多的和最受用户欢迎的一种应用。电子邮件把邮件发送到收件人使用的邮件服务器,并放在其中的收件人邮箱中,收件人可随时上网到自己使用的邮件服务器进行读取,相当于 “电子信箱”。
- 一个电子邮件系统有三个主要组成构件,即:用户代理、邮件服务器和邮件协议(包括邮件发送协议,如 SMTP,和邮件读取协议,如 POP3 和 IMAP)。用户代理和邮件服务器都要运行这些协议。
- 电子邮件的用户代理就是用户与电子邮件系统的接口,它向用户提供一个很友好的视窗界面来发送和接收邮件。
- 从用户代理把邮件传送到邮件服务器,以及在邮件服务器之间的传送,都要使用 SMTP 协议。但用户代理从邮件服务器读取邮件时,则要使用 POP3(或 IMAP)协议。
基于万维网的电子邮件使用户能够利用浏览器收发电子邮件。用户浏览器和邮件服务器之间的邮件传送使用 HTTP 协议,而在邮件服务器之间邮件的传送仍然使用 SMTP 协议。
简单网络管理协议 SNMP 由三部分组成,即 (1) SNMP 本身,负责读取和改变各代理中的对象名及其状态数值;(2) 管理信息结构 SMI,定义命名对象和定义对象类型(包括范围和长度)的通用规则,以及把对象和对象的值进行编码的基本编码规则 BER;(3) 管理信息库 MIB,在被管理的实体中创建了命名对象,并规定了其类型。
-101-1482-144
- 系统调用接口是应用进程的控制权和操作系统的控制权进行转换的一个接口,又称为应用编程接口 API。API 就是应用程序和操作系统之间的接口。
- 套接字是应用进程和运输层协议之间的接口,是应用进程为了获得网络通信服务而与操作系统进行交互时使用的一种机制。
- 目前 P2P 工作方式下的文件共享在互联网流量中已占据最大的份额,比万维网应用所占的比例大得多。
- BT 是很流行的一种 P2P 应用。BT 采用 “最稀有的优先” 的技术,可以尽早把最稀有的文件块收集到。此外,凡有当前以最高数据率向某个对等方传送文件块的相邻对等方,该对等方就优先把所请求的文件块传送给这些相邻对等方。这样做的结果是,这些对等方相互之间都能够以令人满意的速率交换文件块。
- 当对等方的数量很大时,采用 P2P 方式下载大文件,要比传统的客户 - 服务器方式快得多。
- 在 P2P 应用中,广泛使用的索引和查找技术是分布式散列表 DHT。
习题¶
6-01 互联网的域名结构是怎样的?它与目前的电话网的号码结构有何异同之处?
6-02 域名系统的主要功能是什么?域名系统中的本地域名服务器、根域名服务器、顶级域名服务器以及权限域名服务器有何区别?
6-03 举例说明域名转换的过程。域名服务器中的高速缓存的作用是什么?
6-04 设想有一天整个互联网的 DNS 系统都瘫痪了(这种情况不大会出现),试问还有可能给朋友发送电子邮件吗?
6-05 文件传送协议 FTP 的主要工作过程是怎样的?为什么说 FTP 是带外传送控制信息?主进程和从属进程各起什么作用?
6-06 简单文件传送协议 TFTP 与 FTP 的主要区别是什么?各用在什么场合?
6-07 远程登录 TELNET 的主要特点是什么?什么叫作虚拟终端 NVT?
6-08 解释以下名词。各英文缩写词的原文是什么?
WWW, URL, HTTP, HTML, CGI, 浏览器,超文本,超媒体,超链,页面,活动文档,搜索引擎。
6-09 假定一个超链从一个万维网文档链接到另一个万维网文档时,由于万维网文档上出现了差错而使得超链指向一个无效的计算机名字。这时浏览器将向用户报告什么?
6-10 假定要从已知的 URL 获得一个万维网文档。若该万维网服务器的 IP 地址开始时并不知道。试问:除 HTTP 外,还需要什么应用层协议和运输层协议?
6-11 你所使用的浏览器的高速缓存有多大?请进行一个实验:访问几个万维网文档,然后将你的计算机与网络断开,然后再回到你刚才访问过的文档。你的浏览器的高速缓存能够存放多少个页面?
6-12 什么是动态文档?试举出万维网使用动态文档的一些例子。
6-13 浏览器同时打开多个 TCP 连接进行浏览的优缺点如何?请说明理由。
6-14 请判断以下论述的正误,并简述理由。
6-15 假定你在浏览器上点击一个 URL,但这个 URL 的 IP 地址以前并没有缓存在本地主机上。因此需要用 DNS 自动查找和解析。假定要解析到所要找的 URL 的 IP 地址共经过 n 个 DNS 服务器,所经过的时间分别为 \(RTT_{1}, RTT_{2}, \cdots, RTT_{n}\) 。假定从要找的网页上只需要读取一个很小的图片(即忽略这个小图片的传输时间)。从本地主机到这个网页的往返时间是 \(RTT_{w}\) 。试问从点击这个 URL 开始,一直到本地主机的屏幕上出现所读取的小图片,一共要经过多长时间?
6-16 在上题中,假定同一台服务器的 HTML 文件中又链接了三个非常小的对象。若忽略这些对象的发送时间,试计算客户点击读取这些对象所需的时间。
6-17 在浏览器中应当有几个可选解释程序。试给出一些可选解释程序的名称。
6-18 一个万维网网点有 1000 万个页面,平均每个页面有 10 个超链。读取一个页面平均要 100 ms。请问:要检索整个网点所需的最少时间是多少?
6-19 搜索引擎可分为哪两种类型?各有什么特点?
6-20 试述电子邮件的最主要的组成部件。用户代理 UA 的作用是什么?没有 UA 行不行?
6-21 电子邮件的信封和内容在邮件的传送过程中起什么作用?和用户的关系如何?
6-22 电子邮件的地址格式是怎样的?请说明各部分的意思。
6-23 试简述 SMTP 通信的三个阶段的过程。
6-24 试述邮局协议 POP 的工作过程。在电子邮件中,为什么需要使用 POP 和 SMTP 这两个协议?IMAP 与 POP 有何区别?
6-25 MIME 与 SMTP 的关系是怎样的?什么是 quoted-printable 编码和 base64 编码?
6-26 一个二进制文件共 3072 字节长。若使用 base64 编码,并且每发送完 80 字节就插入一个回车符 CR 和一个换行符 LF,问一共发送了多少个字节?
6-27 试将数据 11001100 10000001 00111000 进行 base64 编码,并得出最后传送的 ASCII 数据。
6-28 试将数据 01001100 10011101 00111001 进行 quoted-printable 编码,并得出最后传送的 ASCII 数据。这样的数据用 quoted-printable 编码后,其编码开销有多大?
6-29 电子邮件系统需要将人们的电子邮件地址编成目录以便于查找。要建立这种目录应将人名划分为几个标准部分(例如,姓、名)。若要形成一个国际标准,那么必须解决哪些问题?
6-30 电子邮件系统使用 TCP 传送邮件。为什么有时我们会遇到邮件发送失败的情况?为什么有时对方会收不到我们发送的邮件?
6-31 基于万维网的电子邮件系统有什么特点?在传送邮件时使用什么协议?
6-32 DHCP 协议用在什么情况下?当一台计算机第一次运行引导程序时,其 ROM 中有没有该主机的 IP 地址、子网掩码或某个域名服务器的 IP 地址?
6-33 什么是网络管理?为什么说网络管理是当今网络领域中的热门课题?
6-34 解释下列术语:网络元素、被管对象、管理进程、代理进程和管理信息库。
6-35 SNMP 使用 UDP 传送报文。为什么不使用 TCP?
6-36 为什么 SNMP 的管理进程使用探询掌握全网状态属于正常情况,而代理进程用陷阱向管理进程报告属于较少发生的异常情况?
6-37 SNMP 使用哪几种操作?SNMP 在 Get 报文中设置了请求标识符字段,为什么?
6-38 什么是管理信息库 MIB? 为什么要使用 MIB?
6-39 什么是管理信息结构 SMI? 它的作用是什么?
6-40 用 ASN.1 基本编码规则对以下 4 个数组 (SEQUENCE-OF) 进行编码。假定每一个数字占用 4 个字节。
2345, 1236, 122, 1236
6-41 SNMP 要发送一个 GetRequest 报文,以便向一个路由器获取 ICMP 的 icmpInParmProbs 的值。在 icmp 中变量 icmpInParmProbs 的标号是 5,它是一个计数器,用来统计收到的类型为参数问题的 ICMP 差错报告报文的数目。试给出这个 GetRequest 报文的编码。
6-42 对象 tcp 的 OBJECT IDENTIFIER 是什么?
6-43 在 ASN.1 中,IP 地址 (IPAddress) 的类别是应用类。若 IPAddress = 131.21.14.2,试求其 ASN.1 编码。
6-44 什么是应用编程接口 API? 它是应用程序和谁的接口?
6-45 试举出常用的几种系统调用的名称,说明它们的用途。
6-46 图 6-37 表示了各应用协议在层次中的位置。
(1) 简单讨论一下为什么有的应用层协议要使用 TCP 而有的却要使用 UDP?
(2) 为什么 MIME 画在 SMTP 之上?
(3) 为什么路由选择协议 RIP 放在应用层?

6-47 现在流行的 P2P 文件共享应用程序都有哪些特点?存在哪些值得注意的问题?
6-48 使用客户 - 服务器方式进行文件分发。一台服务器把一个长度为 \(F\) 的大文件分发给 \(N\) 个对等方。假设文件传输的瓶颈是各计算机(包括服务器)的上传速率 \(u\) 。试计算文件分发到所有对等方的最短时间。