目录
2.1 应用层协议原理
研发网络应用程序的核心是写出能够运行在不同的端系统和通过网络彼此通信的程序。当研发新应用程序时,我们无需也无法编写在网络核心设备如路由器或链路层交换机上运行的软件,即应用层下的层次对于应用层而言是透明的。
2.1.1 网络应用程序体系结构
首先注意区分网络体系结构和应用程序体系结构。网络体系结构一般是固定的,即五层结构(应用层、传输层、网络层、数据链路层、物理层),应用程序体系结构是由应用程序研发者设计,规定了如何在各种端系统上组织该应用程序。在选择应用程序体系结构时,应用程序研发者一般会使用一下三种主流结构之一:客户-服务器体系结构(CS结构)、P2P对等结构和混合结构。下面介绍这三种结构:
客户-服务器体系结构。有一个总是打开的主机称为服务器,它服务于来自许多其它称为客户的主机的请求。一个典型的例子是Web应用程序,其中总是打开的Web服务器服务来自浏览器(运行在客户主机上)的请求。服务器和客户机特点如下:服务器必须7*24小时提供服务,并且提供永久性访问地址/域名,同时可利用大量服务器实现可扩展性;客户机通过与服务器通信,使用服务器提供的服务,可以间歇性接入网络,可能使用动态IP地址,并且客户机之间不直接通信。在一个客户-服务器应用中,常常会出现一台单独服务器主机跟不上它所有客户请求的情况(这就是为什么需要利用大量服务实现可扩展性)。例如,一个流行的社交网络站点如果仅有一台服务器来处理所有请求,将很快变得不堪重负。为此,配备大量主机的数据中心(data center)常被用于创建强大的虚拟服务器。
P2P对等结构。该结构没有永远在线的服务器,任意端系统/节点之间可以直接通信,节点可间歇性接入网络,节点可能改变IP地址。其优点是高度可伸缩,缺点是难于管理。
混合结构。该结构结合了客户-服务器和P2P的元素,例如对于许多即时讯息应用而言,服务器被用于跟踪用户的IP地址(C/S结构),但用户到用户的报文在用户主机(无需经过中间服务器)直接传送(P2P结构)。每个节点向中央服务器登记自己有哪些内容(比如视频、音乐等文件)可以共享,当其它节点想查找自己感兴趣的内容时,就可以向中央服务器发出查询请求。
2.1.2 进程通信
同一主机上的进程通信由操作系统提供的进程间通信机制负责,不同主机间的进程通过消息交换进行通信。
1.客户与服务器进程
客户与服务器进程的描述。在一对进程之间的通信会话场景中,发起通信(即在该会话开始时发起与其它进程的联系)的进程被标识会客户,在会话开始时等待联系的进程是服务器。注意,客户和服务器并非指的是计算机,而是进程。在P2P中,也存在客户与服务器之分,当对等方A请求对等方B发送一个特定的文件时,在这个特定的通信会话中对等方A是客户,而对等方B是服务器。
2.进程与计算机网络之间的接口
套接字的形象描述。如上所述,多数应用程序是由通信进程对组成,每对中的两个进程互相发送报文。从一个进程向另一个进程发送的报文必须通过下面的网络。进程通过一个称为套接字(socket)的软件接口向网络发送报文和从网络接收报文。我们考虑一个类比来帮助我们理解进程和套接字。进程可类比于一座房子,而它的套接字可以类比于它的门。当一个进程想向位于另外一台主机上的另一个进程发送报文时,它把报文推出该门(套接字)。该发送进程假定该门到另外一侧之间有运输的基础设施,该设施将把报文传送到目的进程的门口。一旦该报文抵达目的主机,它通过接收进程的门(套接字)传递,然后接收进程对该报文进行处理。
套接字的进一步描述。图2.3显示了两个经过因特网通信的进程之间的套接字通信(图2.3中假定由该进程使用的下面运输层协议是因特网的TCP协议)。如该图所示,套接字是同一台主机内应用层与运输层之间的接口。由于该套接字是建立网络应用程序的可编程接口,因此套接字也称为应用程序和网络之间的应用程序编程接口(Application Programming Interface, API)应用程序开发者可以控制套接字在应用层端的一切,但是对该套接字的运输层端几乎没有控制权。应用程序开发者对于运输层的控制仅限于:①选择运输层协议;②也许能设定几个运输层参数,如最大缓存和最大报文段长度等(将在第3章中涉及)。一旦应用程序开发者选择了一个运输层协议(如果可供选择的话),则应用程序就建立在由该协议提供的运输层服务之上。
3.进程寻址
如何在不同主机的不同进程间通信。在主机A运行的进程为了向主机B运行的进程发送分组,那么接收进程就需要有一个地址。为了标识主机B的接收进程,需要定义两种信息:①主机的地址;②在目的主机中指定接收进程的标识符。
主机的地址。在因特网中,主机由其IP地址标识。IP地址是一个32bits的量且能唯一标识某一主机。
主机中进程的标识符。通过为主机上每个需要通信的进程分配一个端口号,有些流行应用有着特定的端口号如HTTP Sever的端口号是80。
进程的标识符=IP地址:端口号。
2.1.3 应用层协议
- 应用层协议的内容
应用层协议定义了运行在不同端系统上的应用程序进程如何相互传递报文。特别是定义了如下:
- 报文类型:请求报文\响应报文
- 不同报文类型的语法,如报文中的各个字段以及这些字段是如何描述的
- 字段的语义,即这些字段中信息的含义
- 规则:确定一个进程何时以及如何发送报文,对报文进行响应的规则。
2.1.4 运输层协议提供的服务
1.可靠数据传输
可靠数据传输出现的原因。分组网络在计算机网络传输过程中可能丢失,例如丢包现象或者分组中某些比特损坏后可能被丢弃。像电子邮件、文件传输等应用,数据丢失可能会产生灾难性的后果,因此,为了支持这些应用,就出现了可靠数据传输。
可靠数据传输的特性。运输层协议能够潜在地向应用程序提供的一个重要服务是进程到进程的可靠数据传输。当一个运输协议提供这种服务时,发送进程只要将其数据传递进套接字,就可以完全相信该数据将能无差错地到达接收进程。 当一个运输层协议不提供可靠数据传输时,由发送进程发送的某些数据可能到达不了接收进程。这可能能被容忍丢失的应用(loss-tolerant-application)所接受,最值得注意的是多媒体应用,如交谈式音频/视频,它们能够承受一定量的数据丢失。在这些多媒体应用中,丢失的数据引起播放的音频/视频出现小干扰,而不是致命的损伤。
2.吞吐率
带宽指的是最大能达到的传输速率,是个静态概念,但是不加严格区分的情况下,可以把带宽和传输速率等同看待。
吞吐率和时延的关系。
吞吐率和延迟并没有直接关系,如果接水速度大于我用水速度(下载视频速度大于视频播放速度),那么就不会卡。因为游戏是实时产生的分组,所以如果某一时刻产生的分组从源到目的的延迟越小,玩的时候也越不卡。
吞吐率作为运输层服务之一的原因。如果因特网电话应用程序对语音以32kbps的速率进行编码, 那么它需要以这个速率向网络发送数据,并以该速率向接收应用程序交付数据。如果运输协议不能提供这种吞吐率,该应用程序或以较低速率进行编码(并且接收足够的吞吐率以维持这种较低的编码速率),或它可能必须放弃发送.这是因为对于这种因特网电话应用而言,接收所需吞吐量的一半是几乎没有或根本没有用处的。具有吞吐率要求的应用程序被称为带宽敏感的应用(如网络视频)(bandwidth-sensitive application),而弹性应用(如Email)能够根据可用的带宽或多或少地利用可供使用的吞吐率。
3.时延
时延作为运输层服务之一的原因。一个例子如:发送方注入进套接字中的每个比特到达接收方的套接字不迟于100ms。这种服务将对交互式实时应用程序有吸引力,如因特网电话、虚拟环境、电话会议和多方游戏,所有这些服务为了有效性而要求数据交付有严格的时间限制。例如,在因特网电话中,较长的时延会导致会话中出现不自然的停顿;在多方游戏和虚拟互动环境中,在做出动作并看到来自环境(如来自位于端到端连接中另一端点的玩家)的响应之间,较长的时延使得它失去真实感。对于非实时的应用,较低的时延总比较高的时延好,但对端时延没有严格的约束。
4.安全性
最后,运输协议能够为应用程序提供一种或多种安全性服务。例如,在发送主机中,运输协议能够加密由发送进程传输的所有数据,在接收主机中,运输层协议能够在将数据交付给接收进程之前解密这些数据。这种服务将在发送和接收进程之间提供机密性,以防该数据以某种方式在这两个进程之间被观察到。
2.1.5 因特网提供的运输层服务
注意,因特网只是计算机网络的一种。因特网为应用程序提供两个运输层协议,即UDP和TCP。当软件开发者为因特网创建一个新的应用时,首要要做出的决定是选择UDP还是TCP。HTTP是应用层协议,TCP和UDP是运输层协议。
1.TCP服务
- 面向连接
客户机和服务器进行报文交换之前,需要在两个进程的套接字之间进行TCP连接,这条连接是全双工的,即连接双方的进程可以在此连接上同时进行报文收发。当应用程序结束报文发送时,必须拆除该连接。
- 可靠的传输
通信进程能够依靠TCP无差错、按适当顺序交付所有发送的数据。
- 流量控制
发送方不会发送速度过快,超过接收方的处理能力。
- 阻塞控制
当网络负载过重时,能够限制发送方的发送速度。
注意:TCP不提供时延保障,不提供最小带宽保障,不提供安全保障。
2.UDP服务
-
无连接
-
不可靠的传输
-
无流量控制、无阻塞控制、不提供时延、带宽、安全保障。
图2-5指出了一些流行的因特网应用所使用的运输协议。可以看到,电子邮件、远程终端访问、Web.文件传输都使用了 TCP。这些应用选择TCP的最主要原因是TCP提供了可靠数据传输服务,确保所有数据最终到达目的地。因为因特网电话应用(如Skype)通常能够容忍某些丢失但要求达到一定的最小速率才能有效工作,所以因特网电话应用的开发者通常愿意将该应用运行在UDP上,从而设法避开TCP的拥塞控制机制和分组开销。但因为许多防火墙被配置成阻挡(大多数类型的)UDP流量,所以因特网电话应用通常设计成如果UDP通信失败就使用TCP作为备份。
2.2 Web和HTTP
2.2.1 Web
1.Web的构成
对象之间通过URL(Uniform Resoure Locator)(统一资源定位器)进行寻址。其格式如下:Scheme://host:port/path。Scheme是协议类型,host是主机名字,port是端口号,path是存储路径。举个例子,https://www.woqu.edu/someDept/pic.gif,其中https是HTTP协议,www.woqu.edu是主机名字,其中端口号省略了,someDept/pic.gif是路径。
2.2.2 HTTP
以下基于万维网来叙述。
1.消息交换过程
当用户请求一个Web页面(如点击一个超链接)时,浏览器向服务器发出对该页面中所包含对象的HTTP请求报文,服务器接收到请求并用包含这些对象的HTTP响应报文进行响应。具体过程如下:
- 服务器在80端口等待请求。
- 浏览器发起到服务器的TCP连接(创建套接字)。
- 服务器接受来自浏览器的TCP连接。
- 浏览器(HTTP客户端)与Web服务器(HTTP服务器)交换HTTP消息。
- 关闭TCP连接。
2.无状态的协议
服务器向客户发送被请求的文件,而不存储任何关于该客户的状态信息。假如某个特定的客户在短短的几秒内两次请求同一个对象,服务器并不会因为刚刚为该客户提供了该对象就不再做出反应,而是重新发送该对象,就像服务器已经完全忘记不久之前所做过的事一样。
3.HTTP连接的两种类型
在许多因特网应用程序中,客户和服务器在一个相当长的时间范围内通信,其中客户发出一系列请求并且服务器对每个请求进行响应。依据应用程序以及该应用程序的使用方式,这一系列请求可以以规则的间隔周期性地或者间断性地一个接一个发出。当这种客户-服务器的交互是经TCP进行的,应用程序的研制者就需要做一个重要决定,即每个请求/响应对是经一个单独的TCP连接发送,还是所有的请求及其响应经相同的TCP连接发送呢?采用前一种方法,该应用程序被称为使用非持久性连接(non-persistent connection),一次连接只传输一个对象;采用后一种方法,该应用程序被称为使用持续性连接(persistent connection),一次连接可传输多个对象。HTTP 1.0版本使用非持久性连接,HTTP 1.1版本默认使用持久性连接。
- 非持久性连接
HTTP1.0采用非持久性连接。假设用户在浏览器中输入URL为www.woqu.edu/home.index,该页面包含一个基本HTML文件和10个JPEG图形,并且这11个对象位于同一台服务器上。整个过程如下:
- HTTP客户端向地址为该URL的服务器发起TCL连接请求。
- HTTP服务器接受TCP连接请求并通知客户端。
- HTTP客户端将HTTP请求消息(包括URL地址)通过TCP连接的套接字发出。
- HTTP服务器收到请求消息并解析,产生包含一个对象的响应消息,并通过套接字发送给客户端。HTTP服务器关闭TCP连接。
- HTTP客户端收到响应消息,解析html文件,显示html文件,发现有10个指向jpeg对象的超链接。
- 为每个jpeg对象重复步骤1-5(重复10次)。
RTT(Round-Trip-Time)指的是一个短分组从客户到服务器然后再返回客户所花费的时间。RTT包括分组传播时延、分组在中间路由器和交换机上的排队时延以及分组处理时延。
请求并接收一个HTML文件所需的时间为建立TCL连接一个RTT,发送请求/响应消息一个RTT,以及服务器传输HTML文件的时间。注意,这只是一个对象所花的时间,而不包括10个jpeg对象。
非持久性连接的问题。第一,必须为每一个请求的对象建立和维护一个全新的连接。对于每个这样的连接,在客户和服务器中都要分配TCP的缓冲区和保持TCP变量,这给Web服务器带来了严重的负担,因为一台Web服务器可能同时服务于数以百计不同的客户的请求。第二,就像我们刚描述的那样,每一个对象经受两倍RTT的交付时延,即一个RTT用于创建TCP,另一个RTT用于请求和接收一个对象。
- 持久性连接
在采用HTTP 1.1持续连接的情况下,服务器在发送响应后保持该TCP连接打开。在相同的客户与服务器之间,后续的请求和响应报文能够通过相同的连接进行传送。特别是,一个完整的Web页面(上例中的HTML基本文件加上10个图形)可以用单个持续TCP连接进行传送。更有甚者,位于同一台服务器的多个Web页面在从该服务器发送给同一个客户时,可以在单个持续TCP连接上进行。
无流水线的持久性连接。客户端只有收到前一个响应消息后才发送新的请求,每个被引用的对象耗时一个RTT(请求和响应)。
带流水线的持久性连接。客户端只要遇到一个引用对象就尽快发出请求,理想情况下,收到所有引用对象只需耗时约一个RTT。
4.HTTP报文格式
HTTP的报文有两种:请求报文和响应报文。下面分别讨论这两种报文:
- 请求报文
详解该报文:
- 报文是用普通的ASCII文本书写的。
- 报文每行都由一个回车和换行符结束,最后一行再附加一个回车换行符。
- 请求报文第一行为请求行,其包含方法字段、URL字段、HTTP版本字段。方法字段可取不同的值,包括GET、POST、HEAD、PUT和DELETE。
- 其后继的行称为首部行。首部行Host: www. someschool. edu指明了对象所在的主 机。 你也许认为该首部行是不必要的,因为在该主机中已经有一条TCP连接存在了。但是, 如我们将在2.2.5节中所见,该首部行提供的信息是Web代理高速缓存所要求的。通 过包含Connection: close首部行,该浏览器告诉服务器不要麻烦地使用持续连接,它要求服务器在发送完被请求的对象后就关闭这条连接。User-agent用来指明用户代理,即向服务器发送请求的浏览器的类型。这里浏览器类型是Mozilla/5.0,即Firefox浏览器。这个首部行是有用的,因为服务器可以有效地为不同类型的用户代理实际发送相同对象的不同版本。(每个版本都由相同的URL寻址。)最后,Accept-language表示用户想得到该对象的法语版本(如果服务器中有这样的对象的话);否则,服务器应当发送它的默认版本。Accept-language:首部行仅是HTTP中可用的众多内容协商首部之一。
这是HTTP请求报文的通用格式,注意到在“首部行”之后还有“实体体”。使用GET方法时实体体为空,而使用POST方法时才使用该实体体。当用户提交表单时,HTTP客户常常使用POST方法,例如当用户向搜索引擎提供搜索关键词时。使用POST报文时,用户仍可以向服务器请求一个Web页面,但Web页面的特定内容依赖于用户在表单字段中输入的内容。如果方法字段的值为POST时,则实体体中包含的就是用户在表单字段中的输入值。
但请注意,当用户提交表单时,也可能会使用GET方法,HTML表单经常使用GET方法,并在(表单字段中)所请求的URL中包括输入的数据。例如,一个表单使用GET方法,它有两个字段,分别填写的是“monkeys”和 **bananas“ , 这样,该URL的结构为 www. somesite. com/animalsearch? monkeys&bananas。 在日复一日的网上冲浪中,你也许已经留意到了这种扩展的URL。
- 响应报文
2.2.3 cookie技术
1.为什么需要cookie
很多应用需要服务器掌握客户端的状态,比如网上购物的购物车记录,cookie的作用就是记录客户端在服务器的状态。
2.cookie的组件
- HTTP响应消息的cookie头部行
- HTTP请求消息的cookie头部行
- 保存在客户端主机上的cookie文件,由浏览器管理
- Web服务器端的后台数据库
3.cookie的工作流程
假设Susan总是从家中PC使用Internet Explorer 上网,她从未访问过Amazon.com联系,但是访问过eBay站点。
Susan第一次访问Amazon时,请求报文到达该Amazon Web服务器时,该Web站点将产生一个唯一识别码,并以此作为索引在它的后端数据库中产生一个表项。接下来Amazon Web服务器用一个包含Set-cookie的首部行的HTTP响应报文对Susan的浏览器进行响应,其中Set-cookie:识别码。例如,该首部行可能是Set-cookie:1678。
当Susan的浏览器收到了该HTTP响应报文时,它会看到该Set-cookie:识别码。该浏览器在它管理的特定cookie文件中添加一行,该行包含服务器的主机名和在Set-cookie中的识别码。值得注意的是该cookie文件已经有了用于eBay的表项,因为Susan过去访问过该站点。当Susan继续浏览Amazon网站时,每请求一个Web页面,其浏览器就会查询该 cookie文件并抽取她对这个网站的识别码,并放到HTTP请求报文中包括识别码的cookie首部行中。特别是,发往该Amazon服务器的每个HTTP请求报文都包括以下首部行Cookie: 1678。
如果Susan再次访问Amazon站点,比如说一个星期后,她的浏览器会在其请求报文中继续放入首部行cookie: 1678O Amazon将根据Susan过去在Amazon访问的网页向她推 荐产品。如果Susan也在Amazon注册过,即提供了她的全名、电子邮件地址、邮政地址和信用卡账号,则Amazon能在其数据库中包括这些信息,将Susan的名字与识别码相关 联(以及她在过去访问过的本站点的所有页面)。这就解释了 Anrnzon和其他一些电子商务网站实现"点击购物(one-click shopping)的道理,即当Susan在后继的访问中选择购买某个物品时,她不必重新输入姓名、信用卡账号或者地址等信息了。
2.2.4 Web缓存
1.简介
Web缓存器也叫代理服务器,它是能够代表初始Web服务器来满足HTTP请求的网络实体。Web缓存器有自己的磁盘存储空间,并在存储空间中保存最近请求过的对象的副本。Web缓存器通常由ISP购买并安装。例如,一所大学可能在它的校园网上安装一台缓存器,并且将所有校园网上的用户浏览器配置为指向它。或者,一个主要的住宅ISP (例如Comcast)可能在它的网络上安装一台或多台Web缓存器,并且预先配置其配套的浏览器指向这些缓存器。
2.Web缓存工作流程
假设浏览器正在请求对象http://www.woqu.com/campus.index将会发生如下情况:
- 浏览器创建一个到Web缓存器的TCP连接,并向Web缓存器中的对象发送一个HTTP请求。
- Web缓存器进行检查,看看本地是否存储该对象副本。如果有,Web缓存器就向客户浏览器用HTTP响应报文返回该对象。
- 如果Web缓存器中没有该对象,它就打开一个与该对象的初始服务器(即www.woqu.com )的TCP连接。Web缓存器则在这个缓存器到服务器的TCP连接上发送一个对该对象的HTTP请求。在收到该请求后,初始服务器向该Web缓存器发送具有该对象的HTTP响应。
- 当Web缓存器接收到该对象时,它在本地存储空间存储一份副本,并向客户的浏览器用HTTP响应报文发送该副本(通过现有的客户浏览器和Web缓存器之间的TCP连接)。
3.部署Web服务器的原因
-
Web缓存器可以大大减少对客户请求的响应时间,特别是当客户与初始服务器之间的瓶颈带宽远低于客户与Web缓存器之间的瓶颈带宽时更是如此。如果在客户与Web缓存器之间有一个高速连接(情况常常如此),并且如果用户所请求的对象在Web缓存器上,则Web缓存器可以迅速将该对象交付给用户。
-
如我们马上用例子说明的那样,Web缓存器能够大大减少一个机构的接入链路到因特网的通信量。通过减少通信量,该机构(如一家公司或者一所大学)就不必急于增加带宽,因此降低了费用。此外,Web缓存器能从整体上大大减低因特网上的Web流量,从而改善了所有应用的性能。
4.一个Web缓存应用例子
5.条件GET方法
出现背景:当用户从Web缓存器中取出对象时,怎么确保该对象是最新版本。条件GET方法就是解决这个问题的。条件GET方法是在HTTP协议之中的。
工作流程:
首先,用户首次点击超链接www.woqu.com/capus.index,此时客户端浏览器先向Web缓存发送HTTP请求报文,Web缓存向该超链接的服务器发送请求报文如下:
GET /capus.index HTTP/1.1 Host:www.woqu.com
其次,服务器向Web缓存器发送具有被请求对象的响应报文如下:
HTTP/1.1 200 OK
Date:Sat, 3 Oct 2015 15:39:29
Sever:Apache/1.3.0
Last-Modified:Wed , 9 Sep 2015 09:23:24
Content-Type:image/gif
(data data data...)
接着Web缓存器将对象转发到客户端浏览器的同时,也在本地缓存了该对象,同时存储了此时该对象最后的修改日期。一个星期后,另一个用户经过该Web缓存器请求同一个对象,该对象仍在这个Web缓存器中。由于在过去的一个星期中位于服务器上的该对象可能已经被修改了,该Web缓存器通过发送一个条件GET执行最新检查,具体而已该Web缓存发送如下报文给服务器:
GET /capus.index HTTP/1.1
Host:www.woqu.com
If-Modified-since:Wed, 9 Sep 2015 09:23:24
值得注意的是,If-Modified-since的值正好等于一星期前服务器发送的响应报文中的Last-Modified。该条件GET报文告诉服务器,仅当自指定日期之后该对象被修改过,才发送该对象。假设该对象自2015年9月9 H 09: 23: 24后没有被修改。接下来的第四步,Web服务器向该缓存器发送一个响应报文:
HTTP/1.1 304 Not Modified
Date:Sat, 10 Oct 2015 15:39:29
Server:Apache/1.3.0
(empty empty empty...)
该响应报文中的304 Not Modified告诉Web缓存器可以直接使用缓存器中的该对象,能向请求的浏览器转发Web缓存器缓存的该对象副本。
2.3 因特网中的电子邮件
2.3.1 电子邮件简介
1.组成部分
电子邮件系统由三个主要组成部分:用户代理(如软件应用邮箱)、邮件服务器和简单邮件传输协议(SMTP)。
2.工作流程
①发送方:发件人调用计算机中的用户代理撰写和编辑要发送的邮件。
②发送邮件:发件人点击屏幕上的“发送邮件”按钮,把发送邮件的工作全都交给用户代理来完成。用户代理把邮件用SMTP协议发给发送方邮件服务器,用户代理充当SMTP客户,而发送方邮件服务器充当SMTP服务器。用户代理所进行的这些工作,用户是看不到的。有的用户代理可以让用户在幕上看见邮件发送的进度显示。用户所使用的邮件服务器究竞在什么地方,用户并不知道,也不必要知道。实际上,用户在把写好的信件交付给用户代理后,就什么都不用管了。
③发送方邮件服务器:SMTP服务器收到用户代理发来的邮件后,就把邮件临时存放在邮件缓存队列中,等待发送到接收方的邮件服务器(等待时间的长短取决于邮件服务器的处理能力和队列中待发送的信件的数量。但这种等待时间一般都远远大于分组在路由器中等待转发的排队时间)。
④发送邮件:发送方邮件服务器的SMTP客户与接收方邮件服务器的SMTP服务器建立TCP连接,然后就把邮件缓存队列中的邮件依次发送出去。请注意,邮件不会在互联网中的某个中间邮件服务器落地。如果SMTP客户还有一些邮件要发送到同一个邮件服务器,那么可以在原来已建立的TCP连接上重复发送。如果SMTP客户无法和SMTP服务器建立TCP连接(例如,接收方服务器过负荷或出了故障),那么要发送的邮件就会继续保存在发送方的邮件缓存队列中,并在稍后一段时间再进行新的尝试。通常是每30分钟进行一次尝试,如果几天后仍不能成功,服务器就删除该报文并以电子邮件形式通知发送方。
⑤接收方邮件服务器:运行在接收方邮件服务器中的SMTP服务器进程收到邮件后,把邮件放入收件人的用户邮箱(邮箱也在邮件服务器中)中,等待收件人进行读取。
⑥读取邮件:收件人在打算收信时,就运行计算机中的用户代理,使用POP3(或IMAP)协议从邮件服务器读取发送给自己的邮件。请注意,在图6-17中,POP3服务器和POP3客户之间的箭头表示的是邮件传送的方向。但它们之间的通信是由POP3客户发起的。
请注意这里有两种不同的通信方式。一种是“推”(push):SMTP客户把邮件“推”给SMTP服务器。另一种是“拉”(pull):POP3客户把邮件从POP3服务器“拉”过来。
2.3.2 SMTP
1.SMTP简介
SMTP和HTTP类似,是应用层协议,使用TCP可靠数据传输服务,主要负责底层的邮件系统如何将邮件从一台机器传至另外一台机器,SMTP规定了在这两个相互通信的SMTP进程之间如何交换信息。
由于SMTP使用客户/服务器模式,因此负责发送邮件的SMTP进程就是SMTP客户,而负责接收邮件的SMTP进程就是SMTP服务器。
同时SMTP限制所有的邮件报文只能采用简单的7比特ASCII表示。然而, 在今天的多媒体时代,7位ASCII的限制的确有点痛苦,即在用SMTP传送邮件之前, 需要将二进制多媒体数据编码为ASCII码,并且在使用SMTP传输后要求将相应的ASCII码邮件解码还原为多媒体数据。2. 2节讲过,使用HTTP传送前不需要将多媒体数据编码为ASCII码。
2.SMTP客户端(C)与服务器端(S)的工作流程
首先在建立TCP连接之后,接收方SMTP服务器要发出“220 Service ready”(服务就绪)。然后SMTP客户向SMTP服务器发送HELO命令,附上发送方的主机名。SMTP服务器若有能力接收邮件,则回答:“250 OK”,表示已准备好接收。若SMTP服务器不可用,则回答“421 Service not available”(服务不可用)。
邮件的传送从MAIL命令开始。MAIL命令后面有发件人的地址。如:MAIL FROM:xiexiren(@tsinghua.org.cn>。若SMTP服务器已准备好接收邮件,则回答“250OK”。否则,返回一个代码,指出原因。如: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<CRLF>,<CRLF>”。这里<CRLF>是“回车换行”的意思。若不能接收邮件,则返回421(服务器不可用),500(命令无法识别)等。接若SMTP客户就发送邮件的内容。发送完毕后,再发送<CRLF>,<CRLF>(两个回车换行中间用一个点隔开)表示邮件内容结束。实际上在服务器端看到的可打印字符只是一个英文的句点。若邮件收到了,则SMTP服务器返回信息“250 OK”,或返回差错代码。
虽然SMTP使用TCP连接试图使邮件的传送可靠,但“发送成功”并不等于“收件人读取了这个邮件”。当一个邮件传送到接收方的邮件服务器后(即接收方的邮件服务器收下了这个邮件),再往后的情况如何,就有好几种可能性。接收方的邮件服务器也可能接着就出了故障,使收到的邮件全部丢失(在收件人读取信件之前)。也可能被邮件服务器的软件当作垃圾邮件删除了。也可能收件人在清理自己的邮箱时,把尚未读取的邮件一起都删除了。有时收件人由于某种原因,很久没有查阅自己的邮箱,根本不知道自己的邮箱中有一些来信。因此,一个邮件即使是“发送成功”,收件人也不一定会读取到这个邮件。尽管如此,基于SMTP的电子邮件通常都被认为是可靠的。
邮件发送完毕后,SMTP客户应发送QUIT命令。SMTP服务器返回的信息是“221(服务关闭)”,表示SMTP同意释放TCP连接。邮件传送的全部过程即结束。
这里再强调一下,使用电子邮件的用户看不见以上这些过程,所有这些复杂过程都被电子邮件的用户代理屏蔽了。
3.与HTTP的对比
- 共同点
①两个协议都是应用层协议,传输层都使用TCP,都用于从一台主机向另一台主机传送文件:HTTP从Web服务器向Web客户(通常是一个浏览器)传送文件(也称为对象);SMTP从一个邮件服务器向另一个邮件服务器传送文件(即电子邮件报文)。
②当进行文件传输时,二者都使用持久性连接。
- 不同点
①HTTP主要是一个拉协议,即某些人在服务器上装载信息,用户使用HTTP从该服务器拉取这些信息,TCP是由想接收文件的机器发起的;SMTP主要是一个推协议,即发送方服务器把文件推向接收方服务器,TCP是由要发送文件的机器发起的。
②SMTP要求每个报文(包括它们的体)采用7比特ASCII码格式。如果某报文包含了非7比特ASCII字符(如具有重音的法文字 符)或二进制数据(如图形文件),则该报文必须按照7比特ASCII码进行编码。HTTP数据则不受这种限制。
③如何处理一个既包含文本又包含图形(也可能是其他媒体类型)的文档。如我们在2. 2节知道的那样,HTTP把每个对象封装到它自己的HTTP响应报文中, 而SMTP则把所有报文对象放在一个报文之中。
2.3.3 邮件报文格式
邮件报文由头部行和消息体组成,头部行包含To、From、Subject以及其它,消息体包含消息本身且消息只能使用ASCII。
一个典型的报文首部如下: 报文里可以通过在头部行增加特定声明可以进行多媒体扩展:
2.3.4 邮件访问协议
典型的用户通常在本地PC上运行一个用户代理程序,而它访问存储在总是保持开机的共享邮件服务器上的邮箱。该邮件服务器与其他用户共享,并且通常由用户的ISP进行维护 (如大学或公司)。
像Bob这样的接收方,是如何通过运行其本地PC上的用户代理,获得位于他的某ISP的邮件服务器上的邮件呢?值得注意的是Bob的用户代理不能使用SMTP得到报文,因为取报文是一个拉操作,而SMTP协议是一个推协议。通过引入一个特殊的邮件访问协议来解决这个难题,该协议将Bob邮件服务器上的报文传送给他的本地PC。目前有一些流行的邮件访问协议,包括第三版的邮局协议(Post Office Protocol—Version 3 , POP3)、因特网邮件访问协议(Internet Mail Access Protocol, IMAP)以及 HTTP。
1.POP3
POP3协议是作用于接收方的邮件服务器和接收方用户代理之间的,当接收方用户代理打开一个到邮件服务器端口110上的TCP连接后,POP3就开始工作了。随着建立TCP连接,POP3按照三个阶段进行工作:特许、事务处理、更新。
特许阶段。用户代理明文形式发送用户名和口令以鉴别用户,主要有两个命令:user <user name>和pass <password>。其具体如下:
事务处理。用户代理取回报文,同时在这个阶段用户代理还能进行如下操作,对报文做删除标记或取消报文的删除标记,以及获取邮件的统计信息。使用POP3的用户代理通常被用户配置为“下载并删除”或者“下载并保留”方式,POP3用户代理发岀的命令序列取决于用户代理程序被配置为这两种工作方式的哪一种。使用下载并删除方式,用户代理发出list、retr和dele命令。举例来说,假设用户在他(她)的邮箱里有两个报文。在下面的对话中, C:(代表客户)是用户代理,S:(代表服务器)是邮件服务器。事务处理过程将类似于如下过程:
更新。在处理quit命令后,POP3服务器进入更新阶段,从用户邮箱中删除邮件1和2。
2.IMAP
使用POP3只能将邮件下载到本地并在本地创建文件夹进行管理,使用IMAP则可以在远程服务器上建立文件夹并在远程服务器上进行管理。
IMAP服务器把每个报文与一个文件夹联系起来;当报文第一次到达服务器时,它与收件人的INBOX文件夹相关联。收件人则能够把邮件移到一个新的、用户创建的文件夹中,阅读邮件,删除邮件等。IMAP协议为用户提供了创建文件夹以及将邮件从一个文件夹移动到另一个文件夹的命令。IMAP还为用户提供了在远程文件夹中查询邮件的命令,按指定条件去查询匹配的邮件。值得注意的是,与POP3不同,IMAP服务器维护了 IMAP会话的用户状态信息,例如,文件夹的名字以及哪些报文与哪些文件夹相关联。
IMAP的另一个重要特性是它具有允许用户代理获取报文某些部分的命令。例如,一个用户代理可以只读取一个报文的报文首部,或只是一个多部分MIME报文的一部分.用户代理和其邮件服务器之间使用低带宽连接(如一个低速调制解调器链路)的时候,这个特性非常有用。使用这种低带宽连接时,用户可能并不想取回他邮箱中的所有邮件,其要避免可能包含如音频或视频片断的大邮件。
2.3.4 基于Web的电子邮件
如今越来越多的用户使用Web浏览器收发电子邮件,其图如下:
总结:无论是平常的电子邮件还是基于Web的电子邮件邮件服务器之间只能使用STMP。基于Web的电子邮件在服务器和代理之间是使用HTTP,平常的电子邮件则是发送方和发送方的服务器使用STMP,接收方和接收方的服务器使用POP3或IMAP。
2.4 DNS
2.4.1 DNS的作用
主机标识方法有两种,一种是主机名,如www.woqu.com,这种方式对于人易读,但对于机器不易读,另一种是IP地址,如127.7.106.83,这种方式对于机器易读,但对于人不易读。DNS(域名系统)的主要作用就是完成主机名到IP地址的映射,让客户能通过主机名输入,底层自动转为IP地址去寻找目的主机。DNS其它作用也有如下:
①主机别名。有着复杂主机名的主机能拥有一个或者多个别名。例如,一台名为relay 1. west-coast, enterprise, com的主机,可能还有两个别名为enterprise. com 和 www. enterprise. com。 在这种'情况下,relay1. west- coast.enterprise.com也称为规范主机名(canonical hostname)。主机别名(当存在时)比主机规范名更加容易记忆。应用程序可以调用DNS来获得主机别名对应的规范主机名以及主机的IP地址。
②邮件服务器别名。应用程序可以调用DNS来获得邮件服务器的主机别名对应的规范主机名以及主机的IP地址。
③负载分配。繁忙的站点(如cnn.com)可能被分布到多台服务器上,也就是说通过多台不同的服务器,都可以访问到该站点,由于每台服务器均运行在不同的端系统上,每个都有着不同的IP地址,这样的话一个IP地址集合对应同一个规范主机名,DNS数据库中存储着这些IP地址集合。当客户对映射到某IP地址集合的名字发出一个DNS请求时,为了避免客户访问该站点时总是访问同一个服务器,DNS会将IP地址集合排序,让客户向排在最前面的IP地址对应的服务器发送HTTP请求报文,每一个客户请求一次该集合就循环排序一次,这样就缓了服务器的压力。
2.4.2 DNS是什么
DNS是一个由分层的DNS服务器实现的分布式数据库,一个使得主机能够查询分布式数据库的应用层协议。
2.4.3 DNS工作流程
假设运行在用户主机上的某些应用程序(如Web浏览器或邮件阅读器)需要将主机名转换为IP地址。这些应用程序将调用DNS的客户端,并指明需要被转换的主机名。用户主机上的DNS接收到后,向网络中发送一个DNS查询报文。所有的DNS请求和回答报文使用UDP数据报经端口 53发送。经过若干毫秒到若干秒的时延后,用户主机上的DNS接收到一个含有所要查找的主机的IP地址的DNS回答报文。这个映射结果则被传递到调用DNS的应用程序。
2.4.4 集中式和分布式DNS服务器
1.集中式DNS服务器
集中式DNS服务器即因特网上只使用一个DNS服务器,该服务器包含所有的映射。在这种集中式设计中,客户直接将所有查询直接发往单一的DNS服务器,同时该DNS服务器直接对所有的查询客户做出响应。尽管这种设计的简单性非常具有吸引力,但它不适用于当今的因特网,因为因特网有着数量巨大(并持续增长)的主机。这种集中式设计的问题包括:
①单点故障。如果该DNS服务器崩溃,整个因特网随之瘫痪!
②通信容量。单个DNS服务器不得不处理所有的DNS査询(用于为上亿台主机产生的所有HTTP请求报文和电子邮件报文服务)。
③远距离的集中式数据库。单个DNS服务器不可能 “邻近”所有查询客户。如果我们将单台DNS服务器放在纽约市,那么所有来自澳大利亚的查询必须传播到地球的另一边,中间也许还要经过低速和拥塞的链路,这将导致严重的时延。
④维护。单个DNS服务器将不得不为所有的因特网主机保留记录。 这不仅将使这个中央数据库庞大,而且它还不得不为解决每个新添加的主机而频繁更新.
2.分布式DNS服务器
DNS使用了大量的DNS服务器,它们以层次方式组织,并分布在全世界范围内。有以下三种类型的DNS服务器:根服务器,顶级域(TLD)服务器和权威服务器。
①根DNS服务器。有400多个根服务器遍及全世界,根服务器提供顶级域服务器的IP地址。
②顶级域服务器。对于每个顶级域(如com、org、net、edu和gov)和所有国家顶级域(如uk、fr、ca和jp)都会TLD服务器。TLD服务器提供了权威DNS服务器的IP地址。
③权威DNS服务器。在因特网上具有公共可访问主机(如Web服务器和邮件服务器)的每个组织机构必须提供公共可访问的DNS记录,这些记录将这些主机的名字映射为IP地址。那么这些组织机构通过什么方式提供这些DNS记录呢?一种方法是组织机构自己实现自己的权威DNS服务器,权威DNS服务器里收藏了这些DNS记录;另一种方法是支付费用让这些记录存储在某个ISP的一个权威DNS服务器中。
除了根、TLD和权威服务器都处在DNS服务器的层次结构中,还有一类重要的DNS服务器称为本地DNS服务器。 严格说来,一个本地DNS服务器并不属于该服务器的层次结构,但它对DNS层次结构是至关重要的。每 个ISP (如一个居民区的1SP或一个机构的ISP)都有一台本地DNS服务器(也叫默认名字服务器)。当主机与某个ISP连接时,该ISP提供一台主机的IP地址,该主机具有一台或多台其本地DNS服务器的IP地址(通常通过DHCP,将在第4章中讨论)。主机的本地DNS服务器通常“邻近”本主机。对某机构ISP而言,本地DNS服务器可能就与主机在同一个局域网中;对于某居民区ISP来说,本地DNS服务器通常与 主机相隔不超过几台路由器。当主机发岀DNS请求时,该请求被发往本地DNS服务 器,它起着代理的作用,并将该请求转发到DNS服务器层次结构中,我们下面将更为详细地讨论。
分布式DNS服务器工作流程之迭代查询和递归查询。假设主机cse.nyu.edu想知道主机gaia.cs.umass.edu的IP地址。首先客户主机cse.nyu.edu先向本地DNS服务器dns.nyu.edu发送一个DNS查询报文。该查询报文含有被转换的主机名 gaia. cs. umass. eduo本地DNS服务器将该报文转发到根DNS服务器。该根DNS服务器注意到其edu前缀并向本地DNS服务器 返回负责edu的TLD的IP地址列表。该本地DNS服务器则再次向这些TLD服务器之一发送查询报文。该TLD服务器注意到umass. edu前缀,并用权威DNS服务器的IP地址进行响应,该权威DNS服务器是负责马萨诸塞大学的dns. umass. eduo最后,本地DNS服务器直接向dns.umass. edu重发查询报文,dns. umass. edu用gaia. cs. umass. edu的IP地址进行响应。注意到在本例中,为了获得一台主机名的映射,共发送了 8份DNS报文:4份查询报文和4份回答报文!我们前面的例子假设了 TLD服务器知道用于主机的权威DNS服务器的IP地址。一般而言,这种假设并不总是正确的。相反,TLD服务器只是知道中间的某个DNS服务器, 该中间DNS服务器依次才能知道用于该主机的权威DNS服务器。例如,再次假设马萨诸塞大学有一台用于本大学的DNS服务器,它称为dns. umass. eduo同时假设该大学的每个系都有自己的DNS服务器,每个系的DNS服务器是本系所有主机的权威服务器。在这种情况下,当中间DNS服务器dns. umass. edu收到了对某主机的请求时,该主机名是以cs.umass.edu结尾,它向dns. nyu. edu返回dns. cs. umass. edu的IP地址,后者是所有以 cs. umass. edu结尾的主机的权威服务器。本地DNS服务器dns. nyu. edu则向权威DNS服务器发送查询,该权威DNS服务器向本地DNS服务器返回所希望的映射,该本地服务器依 次向请求主机返回该映射。在这个例子中,共发送了 10份DNS报文!
从cse. nyu. edu到dns. nyu. edu发出的查询是递归查询,因为该查询以自己的名义请求dns. nyu. edu来获得该映射。而后继的3个查询是迭代查询,因为所有的回答都是直接返回给dns. nyu. edu。
分布式DNS服务器工作流程之纯递归查询。
2.4.5 DNS缓存
DNS缓存原理。在一个请求链中,当某DNS服务器接收一个DNS回答(例如,包含某主机名到IP地址的映射)时,它能将映射缓存在其服务器的本地存储器中。由于主机和主机名与IP地址间的映射并不是永久的,DNS服务器在一段时间后(通常是两天)将丢弃缓存的信息。
举一个例子,假定主机apricot.nyu. edu向dns. nyu. edu查询主机名cnn. com的IP地址,查询完毕后dns.nyu.edu缓存了cnn.com的IP地址。 此后,假定过了几个小时,纽约大学的另外一台主机如kiwi. nyu. edu也向dns. nyu. edu查询相同的主机名。因为有了缓存,该本地DNS服务器可以立即返回cnn. com的IP地址,而不必查询任何其他DNS服务器。本地DNS服务器也能够缓存TLD服务器的IP地址,因而允许本地DNS绕过查询链中的根DNS服务器。事实上,因为缓存,除了少数DNS查询以外,根服务器被绕过了。
2.4.6 DNS记录和报文
每个DNS服务器都存储有资源记录(Resource Record),RR提供了主机名到IP地址的映射。每个DNS回答报文包含了一条或多条RR。 RR是一个包含了下列字段的四元组: (Name,Value,Type,TTL) TTL是该记录的生存时间,它决定RR应当从缓存中删除的时间。在下面给出的RR例子中,我们忽略掉TTL字段。Name和Value的值取决于Type:
- Type=A,(Name,Value)对应(主机名,主机对应的IP地址),例如(relay1.bar.foo.com,145.37.93.126,A),可以通过Name来获取Value。
- Type=NS,(Name,Value)对应(域,查找该域中的主机所要的权威DNS服务器名),例如(foo.com,dns.foo.com,NS),可以通过Name来获取Value。
- Type=CNAME,(Name,Value)对应(主机别名,主机的规范主机名),例如(foo.com,relay1.bar.foo.com,CNAME),可以通过主机别名来获取主机规范名。
- Type=MX,(Name,Value)对应(邮件服务器的别名,邮件服务器的规范主机名),例如(foo.com,mail.bar.foo.com,MX),可以通过邮件服务器别名来获取邮件服务器的规范主机名。由于MX和CNAME的存在,一个公司的邮件服务器和其它服务器(如Web服务器)可以使用相同的别名,为了获取邮件服务器的规范主机名,DNS客户端应当申请一条MX记录,为了获取其他服务器的规范主机名,DNS客户端应当申请一条CNAME记录。
1.DNS报文
DNS只有查询和回答两种报文,且这两种报文有着相同的格式,各字段语义如下所示:
- 前12个字节是首部区域,其中有几个字段。“标识符”是2字节的数,用于标识该查询,这个标识符会被复制到回答报文中,以便让客户用它匹配发送的请求和收到的回答。“标志”字段有若干标志,如“查询/回答”标志位,0表查询,1表回答,如“权威的”标志位,在回答报文中,如果请求的是权威DNS服务器则为1,如“希望递归”标志位,在查询报文中如果希望它执行递归则为1,如“递归可用”标志位,在回答报文中如果该服务器支持递归查询则为1。首部区域的其余四个字段指出了在首部后的4类数据区域出现的数量。
- 问题区域包含着正在进行的查询信息。该区域包括:①名字字段,包含正在被查询的主机名字;②类型字段,指出有关该名字的正被询问的问题类型,例如主机地址是与一个名字相关联(类型A)还是与某个名字的邮件服务器相关联(类型MX)。
- 在来自DNS服务器的回答中,回答区域包含了对最初请求的名字的资源记录。前面讲过每个资源记录中有Type (如A、NS、CNAME和MX)字段、Value字段和 TTL字段。在回答报文的回答区域中可以包含多条RR,因此一个主机名能够有多 个IP地址(例如,就像本节前面讨论的冗余Web服务器)。
- 权威区域包含了其他权威服务器的记录。
- 附加区域包含了其他有帮助的记录。例如,对于一个MX请求的回答报文的回答区域包含了一条资源记录,该记录提供了邮件服务器的规范主机名。该附加区域包含一个类型A记录,该记录提供了用于该邮件服务器的规范主机名的IP地址。
2.在DNS数据库中插入记录
假定你刚刚创建一个称为网络乌托邦(Network Utopia)的令人兴奋的新创业公司。你必定要做的第一件事是在注册登记机构注册域名networkutopia. como 注册登记机构(registrar)是一个商业实体, 它验证该域名的唯一性,将该域名输入DNS数据库(如下面所讨论的那样),对提供的服务收取少量费用。
当你向某些注册登记机构注册域名networkutopia, com时,需要向该机构提供你的基本和辅助权威DNS服务器的名字和IP地址。假定该名字和1P地址是dnsl. networkutopia, com 和 dns2. networkutopia, com 及 212. 212. 212. 1 和 212. 212. 212. 2。 对这两个权威DNS服务器的每一个,该注册登记机构确保将一个类型NS和一个类型A的记录输入TLD com服务器。特别是对于用于networkutopia, com的基本权威服务器,该注册登记机构将下列两条资源记录插入该DNS系统中:(networkutopia.com, dns1.networkutopia.com, NS) (dns1.networkutopia.com, 212.212.212.1,A) 你还必须确保用于Web服务器www. networkutopia.com的类型A资源记录和用于邮件服务器mail.networkutopia.com的类型MX资源记录被输入你的权威DNS服务器中。一旦完成所有这些步骤,人们将能够访问你的Web站点,并向你公司的雇员发送电子邮件。
假定在澳大利亚的Alice要观看www. networkutopia.com的Web页 面。如前面所讨论,她的主机将首先向其本地DNS服务器发送请求。该本地服务器接着则联系一个TLD com服务器(如果TLD com服务器的地址没有被缓存,该本地DNS服务器也将必须与根DNS服务器相联系)。因为注册登记机构将这些资源记录插入所有的TLDcom服务器,所以此时该TLD服务器包含前面列出的类型NS和类型A资源记录。该TLDcom服务 器向Alice的本地DNS服务器发送一个回答,该回答包含了这两条资源记录。该本地DNS服务器则向212. 212. 212. 1发送一个DNS査询,请求对应于www. networkutopia, com的类 型A记录。该记录提供了所希望的Web服务器的IP地址,如212.212.71.4,本地DNS服务器将该地址回传给Alice的主机。Alice的浏览器此时能够向主机212. 212. 71. 4发起一个 TCP连接,并在该连接上发送一个HTTP请求。
2.5 P2P文件分发
2.5.1 P2P体系结构的扩展性
本节通过比较P2P体系结构和CS体系结构来说明P2P体系结构更容易扩展。
首先是CS体系结构。如图2-21所示,服务器和对等方使用接入链路与因特网相连。其中Us表示服务器接入链路的上传速率,Ui表示第i对等方接入链路的上传速率,Di表示了第i对等方接入链路的下载速率。还用F表示被分发的文件长度(以比特计),N表示要获得的该文件副本的对等方的数量。分发时间(distribution time)是所有N个对等方得到该文件的副本所需要的时间。在下面分析分发时间的过程中,我们对客户-服务器和P2P体系结构做了简化(并且通常是准确的[Akella 2003])的假设,即因特网核心具有足够的带宽,这意味着所有瓶颈都在网络接入链路。我们还假设服务器和客户没有参与任何其他网络应 用,因此它们的所有上传和下载访问带宽能被全部用于分发该文件。
接下来计算分发时间。首先服务器必须向N个对等方传输该文件的一个副本,因此服务器必须传输NF比特,因为该服务器的上传速率是Us,则服务器分发该文件的时间必定至少为NF/Us。令Dmin表示具有最小下载速率对等方的下载速率,即Dmin=min{D1,D2,...,Dn},因此具有最小下载速率的对等方至少需要F/Dmin秒时间获得该文件的所有比特。因此CS体系结构分发时间Dcs≥max{NF/Us,F/Dmin},此处我们约取Dcs={NF/Us,F/Dmin},从该式可以看到,当N足够大时,Dcs主要由NF/Us决定,F和Us是一个常量,Dcs是关于N的线性函数。
最后是P2P结构。在P2P结构中,每个对等方只要接收到了某些文件数据,就可以使用自己的上传能力重新将数据分发给其它的对等方。
接下来计算分发时间。在分发的开始,只有服务器具有文件。为了使社区的这些对等方得到该文件,该服务器必须经其接入链路至少发送该文件的每个比特一次。因此,最小分发时间至少是F/Us(与客户-服务器方案不同,由服务器发送过一次的比特可能不必由该服务器再次发送,因为对等方在它们之间可以重新分发这些比特)。与客户-服务器体系结构相同,具有最低下载速率的对等方不能够以小于F/Dmin秒的分发时间获得所有F比特,因此对等方最小分发时间至少为Dmin。最后观察系统整体总上传能力等于服务器上传速率加上所有对等方的上传速率,即Utotal=Us+U1+...+Un,系统必须向这N个对等方总共交付NF比特,因此最小分发时间为NF/Utotal,则Dp2p≥max{F/Us,F/Dmin,NF/Utotal},此处约取Dp2p=max{F/Us,F/Dmin,NF/Utotal}。
最后我们假设所有对等方具有相同的上传速率u,F/u=1小时,Us=10u,Dmin≥Us,则有如下图。
由图可见,随着越来越多的对等方加入,P2P分发文件的时间远小于CS。
2.5.2 P2P系统的索引
索引是信息到节点位置(IP地址+端口号)的映射。其应用有如下:
下面将介绍三种P2P索引技术。
1.集中式索引
①工作流程
中央服务器负责记录各节点共享的文件及对应的地址,作为一个索引功能。当有新节点加入时,会通知中央服务器它所共享的内容以及IP地址。假设Alice查找"Hey Jude",Alice首先向服务器询问谁有"Hey Jude",服务器告诉Alice,Bob有。接下来Alice向Bob请求该文件即可,Bob直接向Alice传输文件,不需要服务器参与。
②特点
- 内容和文件传输是分布式的
- 内容定位是高度集中式的
③问题
- 版权问题
- 性能瓶颈受服务器限制
- 单点失效问题,只要服务器宕机,全得玩完
2.泛洪式查询
①工作流程
首先先接收覆盖网络,节点X和节点Y之间如果有TCP连接,那么构成一条边,所有活动节点和边构成覆盖网络。查询消息时通过已有的TCP连接发送,每个节点收到其它节点发来的查询消息时,如果查询不命中,就会继续通过目前节点的TCP连接将这个查询消息进行转发,如果查询命中则利用反向路径发回最初的查询节点。 ②特点
- 完全分布式架构
- 每个节点对它共享的文件进行索引,且只对它共享的文件进行索引。
③问题
- 查询过于大,给网络带来负担
- 当有新节点加入时,处理复杂
3.层次式覆盖网络
(前两种的结合)
①工作流程
节点有普通节点和超级节点之分,超级节点可连接超级节点,以及部分普通节点,一个普通节点不能被两个或两个以上的超级节点连接,且普通节点和普通节点之间不进行连接。如下图所示。
P2P案例应用:Skype
2.5.3 BitTorrent
BitTorrent是一种用于文件分发的流行的P2P协议。
参与一个特定文件分发的所有对等方被称为一个洪流,在一个洪流中的对等方彼此下载等长度的文件块(chunk),典型的块长度为256KB。当一个对等方首次加入一个洪流时,它没有块。随着时间的流逝,它累积了越来越多的块。当它下载块时,也为其他对等方上载了多个块。一旦某对等方获得了整个文件,它也许(自私地)离开洪流,或(大公无私地)留在该洪流中并继续向其他对等方上载块。同时,任何对等方 可能在任何时候仅具有块的子集就离开该洪流,并在以后重新加入该洪流中。
每个洪流具有一个基础设施节点,称为追踪器(tracker)。当一个对等方加入某洪流时,它向追踪器注册自己,并周期性地通知追踪器它仍在该洪流中。以这种方式,追踪器跟踪参与在洪流中的对等方。一个给定的洪流可能在任何时刻具有数以百计或数以千计的对等方。如图2-23所示,当一个新的对等方Alice加入该洪流时,追踪器随机地从参与对等方的集合中选择对等方的一个子集(为了具体起见,设有50个对等方),并将这50个对等方的IP地址发送给Alice。Alice持有对等方的这张列表,试图与该列表上的所有对等方创建并行的TCP连接。我们称所有这样与Alice成功地创建一个TCP连接的对等方为“邻近对等方”(在图2 23中,Alice显示了仅有三个邻近对等方。通常,她应当有更多的对等方)。随着时间的流逝,这些对等方中的某些可能离开,其他对等方(最初50个以外的)可能试图与Alice创建TCP连接。因此一个对等方的邻近对等方将随时间而波动。
在任何给定的时间,每个对等方将具有来自该文件的块的子集,并且不同的对等方具有不同的子集。Alice周期性地(经TCP连接)询问每个邻近对等方它们所具有的块列表。如果Alice具有L个不同的邻居,她将获得L个块列表。有了这个信息,Alice将对她当前还没有的块发出请求(仍通过TCP连接)。
因此在任何给定的时刻,Alice将具有块的子集并知道它的邻居具有哪些块。利用这些信息,Alice将做出两个重要决定。第一,她应当从她的邻居请求哪些块呢?第二,她应当向哪些向她请求块的邻居发送块?
在决定请求哪些块的过程中,Alice使用一种称为最稀缺优先(rarest Erst)的技术。这种技术的思路是,针对她没有的块在她的邻居中决定最稀缺的块(最稀缺的块就是那些在她的邻居中副本数量最少 的块),并首先请求那些最稀缺的块。这样,最稀缺块得到更为迅速的重新分发,其目标是(大致地)均衡每个块在洪流中的副本数量。
在决定发送块的过程中,Alice对于她的每个邻居都持续性地测量接收比特的速率,并确定以最高速率传输数据给Alice的4个邻居,Alice会向这4个邻居发送块,每过10s,她将重新计算该速率并可能修改这4个对等方的集合。除此之外,每过30s,Alice还要随机向另外一个邻居发送块,我们将这个被随机选择的对等方称为Bob。因为Alice正在向Bob发送数据,她可能成为Bob前4位上传者之一,这样的话Bob将开始向Alice发送数据。如果Bob向Alice发送数据的速率足够高,Bob接下来也能成为Alice的前4位上传者。
2.6 视频流
视频是什么。视频是一系列图像,通常以一种恒定的速率(如每秒24或30张图像)来展示。一幅未压缩的图像由像素阵列组成,其中每个像素由一些比特编码来表示亮度和颜色。视频的一个重要特征是它能够被压缩,因而可以用比特率来权衡视频质量。今天现成的算法可以将一个视频压缩成任何所希望的比特率,比特率越高,则像素越好,图像质量越高,视频质量越高。
当下的视频传输模式。首先是媒体将预先录制好的视频放置在服务器上,用户按需向这些服务器发送请求来观看视频,如Youtube。
HTTP流。在HTTP流中,视频只是存储在HTTP服务器中作为一个普通的文件,每个文件有一个特定的URL。当用户要看该视频时,客户与服务器创建一个TCP连接并发送对该URL的HTTP GET请求。服务器则以底层网络协议和流量条件允许的尽可能快的速率,在一个HTTP响应报文中发送该视频文件。在客户一侧,字节被收集在客户应用缓存中。一旦该缓存中的字节数量超过预先设定的门限,客户应用程序就开始播放,特别是,流式视频应用程序周期性地从客户应用程序缓存中抓取帧,对这些帧解压缩并且在用户屏幕上展现。因此,流式视频应用接收到视频就进行播放,同时缓存该视频后面部分的帧。
DASH。尽管HTTP流在实践中已经得到广泛部署(例如,自YouTube发展初期开始),但它具有严重缺陷,即所有客户接收到相同编码的视频,尽管对不同的客户或者对于相同客户的不同时间而言,客户可用的带宽大小有很大不同,这样就会导致可能存在带宽小而产生视频重大延迟。因此产生了一种基于HTTP流的开发,称为经HTTP的动态适应性流(DASH)。在DASH中,视频编码为几个不同的版本,其中每个版本 具有不同的比特率,对应于不同的质量水平’客户动态地请求来自不同版本且长度为几秒的视频段数据块。当可用带宽量较高时,客户自然地选择来自高速率版本的块;当可用带宽量较低时,客户自然地选择来自低速率版本的块。客户用HTTP GET请求报文一次选择—个不同的块。使用DASH后,每个视频版本存储在HTTP服务器中,每个版本都有一个不同的URL。HTTP服务器也有一个告示文件(manifest file),为每个版本提供了一个URL及其比特率。客户首先请求该告示文件并且得知各种各样的版本。然后客户通过在HTTP GET请求报文中对每块指定一个URL和一个字节范围,一次选择一块。在下载块的同时,客户也测量接收带宽并运行一个速率决定算法来选择下次请求的块。自然地,如果客户缓存的视频很多,并且测量的接收带宽较高,它将选择一个高速率的版本。同样,如果客户缓存的视频很少,并且测量的接收带宽较低,它将选择一个低速率的版本。因此DASH允许 客户自由地在不同的质量等级之间切换。
2.7 内容分发网
出现背景。因特网视频公司要向世界各地的用户按需分发每秒数兆比特的流,一种直观的做法是在某一处建立一个大规模的服务器数据中心,在数据中心中存储其所有视频,并直接向数据中心向世界范围内的客户传输流式视频。但是这种做法存在三个问题:①可能存在传输距离远,途径多个节点,因此传输链路带宽大小不一,导致吞吐量受限;②对于同一个视频,客户每请求一次就要发送一次,浪费网络带宽;③单点失效问题。
内容分发网(CDN)概述。CDN可视为一个组织,它拥有并且管理分布在多个地理位置上的服务器,并在它的服务器中存储视频和其他文件的副本,并且试图将每个用户请求定向到一个将提供最好的用户体验的CDN服务器位置。
CDN分类。CDN可以是专用CDN,即它有内容提供商自己拥有,也可以是第三方CDN,它可以为多个内容提供商分发内容。
CDN服务器两种安置原则。第一种是通过在遍及全球的接入ISP中部署服务器集群来深入到ISP的接入网中,即以ISP为中心,其目标是靠近端用户,通过减少端用户和CDN集群之间(内容从这里收到)链路和路由器的数量,从而改善了用户感受的时延和吞吐量。因为这种高度分布式设计,维护和管理集群的任务成为挑战。第二种是通过在少量(例如10个)关键位置建造大集群来邀请到ISP做客,即以CDN服务器集群为中心。不是将集群放在接入1SP中,这些CDN通常将它们的集群放置在因特网交换点(1XP)。与第一种原则相比,这种设计通常产生较低的维护和管理开销,可能以对端用户的较高时延和较低吞吐量为代价。
CDN跨集群。一旦CDN的集群准备就绪,它就可以跨集群复制内容。CDN可能不希望将每个视频的副本放置在每个集群中,因为某些视频很少观看或仅在某些国家中流行。事实上,许多CDN没有将视频推入它们的集群,而是使用一种简单的拉策略:如果客户向一个未存储该视频的集群请求某视频,则该集群检索该视频(从某中心仓库或者从另一个集群),向客户流式传输视频时的同时在本地存储一个副本。类似于因特网缓存(参见2.2.5节),当某集群存储器变满时,它删除不经常请求的视频。
CDN具体操作。DNS域名解析过程_哔哩哔哩_bilibili。假设一个内容提供商NetCinema雇佣了第三方CDN公司KingCDN来向其客户分发视频,在NetCinema的Web网页上,它的每个视频都被指派了一个URL,该URL包括了字符串“video”以及该视频本身独特的标识符。假设用户正在访问NetCinema的网页,点击其中一个视频链接http://video.netcinema.com/ABCD时,完整发生步骤如下:①浏览器调用其主机上的解析器(相当于DNS客户端),解析器帮助浏览器调用系统的网络功能;②DNS客户端向本地DNS服务器查询IP地址,如果本地缓存了该域名的IP地址,则直接返回IP地址给用户,否则进行下一步;③本地DNS服务器向根域名服务器查询,根域名服务器返回顶级域名服务器的域名列表及对应的IP地址给本地DNS服务器;④本地DNS服务器向其中一顶级域名服务器查询,顶级域名服务器返回权威域名服务器的列表及对应的IP地址;⑤本地DNS服务器向其中一权威服务器查询,权威服务器并不是返回IP地址,而是只返回一个KingCDN域的主机名给本地DNS服务器,如a1105.kingcdn.com;⑥本地DNS服务器访问这个主机(直接输入这个主机名),从这时起,DNS请求进入了KingCDN专用DNS基础措施,KingCDN的DNS系统最终向本地DNS服务器返回KingCDN内容服务器的IP地址(正是在此处KingCDN的DNS系统中指定了某一个CDN内容服务器);⑦本地DNS服务器向用户主机转发这个KingCDN内容服务器的IP地址,并与该服务器建立了一条直接的TCP连接。
其详细可见B站视频,简略可见下图。
CDN部署策略。 任何CDN部署,核心都是集群选择策略,即动态地将客户定向到CDN中的某个服务器集群或数据中心的机制。如我们刚才所见,经过客户的DNS查找,CDN得知了该客户的LDNS服务器的IP地址。在得知该IP地址之后,CDN需要基于该IP地址(是LDNS服务器的IP地址)选择一个适当的集群。CDN —般采用专用的集群选择策略。我们现在简单地 介绍一些策略,每种策略都有其优点和缺点。①地理上最为邻近策略。但对于某些客户,该解决方案可能执行的效果差,因为就网络路径的长度或跳数而言,地理最邻近的集群可能 并不是最近的集群。此外, 种所有基于DNS的方法都内在具有的问题是,某些端用户配置使用位于远地的LDNS,在这种情况下,LDNS位置可能远离客户的位置。此外,这种简单的策略忽略了时延和可用带宽随因特网路径时间而变化,总是为特定的客户指派相同的集群。②基于当前流量条件为客户决定最好的集群。CDN能够对其集群和客户之间的时延和丢包性能执行周期性的实时测量。例如,CDN能够让它的每个集群周期性地向位于全世界的所有LDNS发送探测分组(例如,ping报文或DNS请求)。 这种方法的一个缺点是许多LDNS被配置为不会响应这些探测。
2.8 Socket编程
2.8.1 应用编程接口(API)
应用编程接口API就是在应用进程的控制权和操作系统的控制权进行转换的一个系统调用接口。套接字Socket就是一种典型的API。
网络应用程序有两类。一类是由协议标准中定义的操作的实现,这样的应用程序称为“开放”,因为定义其操作的规则为人们所共知。另一类是专用的网络应用程序,由客户和服务器程序应用的应用层协议没有公开发布在某RFC中或其他地方。某单独的开发者(或开发团队)产生了客户和服务器程序,并且该开发者用他的代码完全控制该代码的功能。但是因为这 些代码并没有实现一个开放的协议,其他独立的开发者将不能开发出和该应用程序交互的代码。
2.8.2 Socket简介
Socket比喻。假设把一台主机比作一个小区,Socket可以比作一户人家的一扇门,门内是应用层,由应用进程控制,门外是其余层,由操作系统控制。假设位于A小区的a想给位于B小区的b写封信,于是a只要在门内家里进行写信,并且遵守寄信的格式(应用层协议),把b的地址填上以及贴邮票等,对于b的地址,a不仅要写小区的位置(主机的IP地址),还要写清楚b的门牌号(端口号),写完然后把信从门缝递给邮政小哥,就有邮政小哥来帮a把信送到b处(a并不知道邮政小哥是怎么送的,即传输层等对应用层是透明的),b只要在门里从门缝里接收快递小哥送到来的信件即可。
Socket管理及寻址。套接字对外可以通过主机IP地址和端口号来寻找其它套接字,对内的话是由操作系统管理,即每个进程有一个套接字描述符表,当应用进程创建套接字时,操作系统分配一个数据结构存储该套接字的相关信息,并返回套接字描述符。
Socket的类型。
2.8.3 UDP套接字编程
基本描述。当使用UDP时,发送方必须先将目的地址以及源地址附在该分组之上(将源地址附在分组之上通常并不是由UDP应用程序代码所为,而是由底层操作系统自动完成的)。在该分组传过发送方的套接字之后,因特网将使用该目的地址通过因特网为该分组选路到接收进程的套接字。当分组到达接收套接字时,接收进程将通过该套接字取回分组,然后检查分组的内容并采取适当的动作。注意,在客户发送报文之前,服务器必须作为一个进程在允许。
具体案例。假设客户程序被称为UDPClient.py,服务器程序被称为UDPServer.py,12000作为服务器的端口号。
2.8.4 TCP套接字编程
基本描述。 当创建TCP连接时,我们将客户套接字地址和服务器套接字地址关联起来,当一侧要向另一侧发送数据时,只需经过套接字将数据丢进TCP连接(这与UDP不同,UDP服务器和客户端在将分组丢进套接字之前必须附上一个目的地址)。TCP服务器还有一个新的地方,即客户生成其套接字时,首先指定服务器的欢迎套接字,服务器是通过欢迎套接字与客户套接字进行三次握手,然后再创建一个新的套接字(称为连接套接字)与客户进行连接传递数据,这样做使为了实现同时进行多个TCP连接)。
具体案例。
2.8.5 套接字编程相关函数(WinSock为例)
1.WSAStartUp
- 作用:使用Socket应用程序在调用Socket之前必须先调用WSAStartUp函数
- 函数:int WSAStartUp(WORD wVersionRequested,LPWSADATA lpWSAData);
- 参数/返回值: 第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本,低位字节指明主版本,例如0x102表示1.2版;第二个参数是指向WSADATA结构的指针,返回实际调用的WinSock的版本信息。
2.WSACleanup
- 作用:使用Socket应用程序在调用Socket之后最后调用的WSACleanup函数
- 函数: int WSACleanup(void);
- 参数/返回值:解除与Socket库的绑定,释放Socket库所占用的系统资源。
3.Socket
- 作用:创建套接字
- 函数:sd = socket(protofamily,type,proto);
- 参数/返回值:第一个参数指明协议族,protofamily=PF_INET表明是TCP/IP的;第二个参数指明套接字类型,type=SOCK_STREAM,SOCK_DGRAM or SOCK_RAW;第三个参数指明协议号(0为默认),返回值为套接字描述符。
4.Closesocket
- 作用:关闭一个描述符为sd的套接字
- 函数:int Closesocket(SOCKET sd);
- 参数/返回值:如果多个进程共享一个套接字,调用Closesocket将套接字引用计数减一,减至0才关闭;一个进程中的多线程对一个套接字的使用无计数,如果进程中的一个线程调用Closesocket将一个套接字关闭,该进程中的其它线程也将不能访问该套接字。返回值为0表示成功。
5.bind
- 作用:将一个套接字与本地的某一端点地址(IP地址+端口号)进行绑定。注意,客户程序一般不必调用bind,因为操作系统会帮助我们去设置这个客户端本地的IP地址和端口号。服务器一般绑定的IP地址为地址通配符INADDR_ANY,因为服务器主机可能连接多个网口,如果只绑定一个IP地址,那么客户从另一IP地址发起请求,则服务器无法接收到。
- 函数:int bind(sd,localaddr,addrlen);
- 参数/返回值:sd为套接字描述符,localaddr为某一端点地址,addrlen为地址长度。
6.listen
-
作用:置服务器端的流套接字处于监听状态,仅用于服务器端且仅用于面向连接的流套接字,且可以设置连接请求队列大小,因为一个套接字一次只能连接一个,其余想请求连接的得在队列中等待。
-
函数:int listen(sd,queuesize);
-
参数/返回值:sd为套接字描述符,queuesize为请求队列大小,返回值为0表示成功,SOCKET_ERROR表示失败。
7.connect
- 作用:客户程序调用该函数来使客户套接字(sd)与特定计算机的特定端口(saddr)的套接字进行连接,这个函数仅用于客户端。可用于TCP客户端也可用于UDP客户端。UDP调用该函数并没有进行连接(因为UDP不是面向连接的),它只是指定服务器端口地址而已。
- 函数:connect(sd,saddr,saddrlen);
- 参数/返回值:sd为套接字描述符,saddr为服务器端口地址,saddrlen为地址长度。
8.accept
- 作用:服务器程序调用accept函数从处于监听状态的流套接字sd的客户连接请求队列中取出排在最前面的一个客户请求,并且创建一个新的套接字(连接套接字)与客户套接字创建连接通道。仅用于TCP套接字和服务器。
- 函数:newsock = accept(sd,caddr,caddrlen);
- 参数/返回值:sd为服务器套接字描述符,caddr为客户套接字地址,caddrlen为地址长度,返回值为一个新的套接字的描述符。
9.send/sengto
- 作用:用于发送数据。send用于TCP套接字或调用了conncet函数的UDP客户端套接字,sendto用于UDP服务器端套接字或未调用connect函数的UDP客户端套接字。
- 函数:send(sd,*buf,len,flags); sendto(sd,*buf,len,flags,destaddr,addrlen);
10.recv/recvfrom
- 作用:recv函数从TCP连接的另一端接收数据,或者从调用了connect函数的UDP客户端套接字接收服务器发来的数据;recvfrom函数用于从UDP服务器端套接字与未调用connect函数的UDP客户端套接字接收对端数据。
- 函数:recv(sd,*buffer,len,flags); recvfrom(sd,*buffer,len,flags,senderaddr,saddrlen);
11.setsockopt/getsockopt
- 作用:设置套接字的参数
API函数小结: