计算机网络原理:应用层
todo
一、计算机网络应用体系结构
1.1、客户/服务器(C/S)结构
客户/服务器(C/S)结构网络应用的通信双方分为服务器程序和客户程序,服务器程序需要先运行,做好接受通信的准备,客户程序后运行,主动请求与服务器进行通信。服务器计算机通常也称为服务器,一般具有固定的网络地址(比如IP地址),长期运行,以便服务器软件能够随时被请求服务。客户软件通常运行在普通用户的计算机或其他计算设备上,可能使用动态的网络地址,是通信的主动发起方。
C/S网络应用最主要的特征是,通信只在客户与服务器之间进行,客户与客户之间不进行直接通。在C/S通信过程中,主动发起通信的一方就是客户,被动接受通信的一方就是服务器。
1.2、纯P2P结构
P2P网络应用在文件分发、文件共享、视频流服务等应用中表现出优越的性能。在纯 P2网络应用中,所有通信都是在对等的通信双方之间直接进行,通信双方没有传统意义上的客户与服务器之分,即“地位”对等。
对等端软件通常运行在普通用户的计算设备上,可以动态地直接与其他对等端进行通信。因此,P2P应用中的每个对等端都同时具备C/S应用的客户与服务器的特征,是一个服务器与客户的结合体。
1.3、混合结构
混合结构网络应用将C/S应用与P2P 应用相结合,既有中心服务器的存在,又有对等端(客户)间的直接通信。
在混合结构网络应用中,通常每个客户通过C/S方式向服务器注册自己的网络地址,声明可共享的资源或可提供的服务,并通过中心服务器发现其他在线的客户,检索其他客户可共享的资源等信息。当某客户希望获取另一个客户拥有的资源或服务时,便直接与该客户发起通信,请求其提供服务。
二、网络应用通信基本原理
2.1、网络应用的基本通信过程
网络应用的本质是运行在不同主机上(当然也可以运行在同一主机上)的应用进程之间的通信。
网络应用的基本通信过程就是运行在不同主机上的应用进程间以C/S方式进行的通信,服务器端运行的是服务器进程,被动地等待客户请求服务;客户端运行的是客户进程,主动起通信,请求服务器进程提供服务。应用进程间遵循应用层协议交换应用层报文。
2.2、网络应用与传输层服务
网络应用需要使用传输层提供端到端的传输服务,不同应用对传输层服务有不同的服务性能需求,有的应期望传输提供可靠的数据传输服务,有的应用期望传输层提供延时保障服务等。
TCP服务模型包括面向连接服务和可靠数据传输服务。当某个应用程序调用TCP作其传输协议时,该应用程序就能获得来自 TCP的这两种服务。
面向连接的服务:在应层报文开始传送之前,TCP客户和服务器互相交换传输层控制信息,完成握手,在客户进程与服务器进程的套接字之间建立一条逻辑的 TCP连接。这条连接是全双工的。当应程序结束报文发送时,必须拆除该连接。
可靠的数数据传输服务:应用进程能够依靠 TCP实现端到端的无差错、按顺序交付所有发送数据的服务。
UDP是一种不提供传输服务保障的轻量级传输层协议,仅提供最小的“尽力”服务。UDP是无连接的,因此在两个进程通信前没有握手过程。
2.3、应用层协议
应用层协议定义了应用进程间交换的报文类型、报文构成部分具体含义以及交换时序等内容,即语法、语义和时序等协议三要素内容。
无论是服务器进程还是客户进程,当其遵循应用层协议组织好应用层报文后,需要通过层间接口(如应用编程接口 API)将报文传递给相邻的传输层,请求传输层协议提供的端到端传输服务。
2.4、套接字(Socket)
套接字(Socket)是每个应用进程与其他应用进程进行网络通信时,真正收发报文的通道。一个应用进程可以创建多个套接字与同—个或不同的传输层协议进行接口。对于一个传输层协议,需要为与其接口的每个套接字分配一个编号,标识该套接字,其编号称为端口号(port number)。
三、域名系统(DNS)
3.1、层次化域名空间
为了实现域名的有效管理与高效查询,DNS服务器采用了层次结构组织方式,并且该层次结构与域名的结构相对应。
域名是一个层次树状结构,其结构由标号序列组成,各标号之间用点隔开,例如,”···.三级域名.二级域名.顶级域名“,各标号分别代表不同级别的域名,如下图所示。
顶级域名可分为三类:
- 国家顶级域名(nTLD):如cn表示中国,us表示美国,uk表示英国等。
- 通用顶级域名(gTLD):如com表示公司和企业、net表示网络服务机构、org表示非盈利性组织、edu表示专用的教育机构、gov表示专用的政府部门、mil表示专用的军事部门、int表示国际组织
- 基础结构域名(infrastructure domain):这类域名只有一个,即arpa,用于反向域名解析,因此又称为反向域名。
3.2、域名服务器
域名服务器的管辖范围不是以“域”为单位,而是以“区”为单位。一个域名服务器所负责管辖的(或有权限的)范围叫作区(zone)。每一个区设置相应的权威名服务器,用来保存该区中的所有主机的域名到 IP地址的映射。
根据域名服务器主要保存的域名信息以及在域名解析过程中的作用等,可将域名服务器分为4类:
- 根域名服务器。是最重要的域名服务器。每个根域名服务器都知道所有的顶级域名服务器的域名和IP 地址。在因特网上,共有13个不同IP地址的根域名服务器,它们的名字是用一个英文字母命名,从a一直到m(前13个字母),如a.rootservers.net, b.rootservers.net、……、m.rootservers.net。
- 顶级域名服务器。即TLD服务器,负责管理在该顶级域名服务器注册的所有二级域名。顶级域名服务器的名称对应一个域名的最后一个名字,是对一个行业的命名,如com、org等,或对一个区域的命名,如cn、us等。
- 权威域名服务器。负责一个区的域名服务器,保存该区中的所有主机的域名到 IP地址的映射。任何一个拥有域名的主机,其域名与 IP地址的映射关系等信息都存储在所在网络的权威域名服务器上。在进行域名解析时,只要查询到被查询域名主机注册的权威域名服务器,就可以获得该域名对应的 IP地址信息。
- 中间域名服务。既不是根域名服务器,又不是顶级域名服务器,也不是权威域名服务器的域名服务器,这些域名服务器通常称为中间域名服务器。例如,某主机域名为www.abc.xyz.com,则可能存在的域名服务器包括顶级域名服务器com,中间域名服务器xyz.com,权威域名服务器abc.xyz.com。
任何一台主机在网络地址配置时,都会配置一个域名服务器作为默认域名服务器。默认域名服务器通常称为本地名服务器,是主机进行域名查询过程中首先被查询的域名服务器。每当主机需要进行域名解析,都会将域名查询请求发送给默认域名服务器;默认域名服务器如果保存了被查询域名的信息,则直接做出响应,如果没有,则代理查询其他域名服务器,直到查询到结果,最后将查询结果发送给查询主机。
3.3、域名解析过程
域名解析分为递归解析和迭代解析。提供递归查询服务的域名服务器,可以代替主机或其他域名服务器,进行进一步的域名查询,并将最终解析结果发送给主机或服务器;提供迭代查询的服务器,不会代替主机或其他域名服务器,进行进一步的查询,而是将下一步要查询的服务器告知主机或服务器。
通常本地域名服务器都提供递归查询服务。主机在进行域名查询时,本地域名服务器如果没有被查询域名的信息,则本地域名服务器代理主机查询根域名服务器或其他域名服务器,直到得到被查询域名的IP地址(当然,也可能查询不到),最后将解析结果发送给主机。域名解析的递归查过程如下图所示。
仅提供迭代查询服务的域名服务器不会代理客户的查询请求,而是将最终结果或者下一步要查询的域名服务器直接响应给查询客户。根域名服务器通常只提供迭代查询服务,当域名服务器收到本地域名服务器的迭代查询请求报文时,要么给出所要查询的IP地址(这种情况不多见),要么在响应报文中告诉本地域名服务器下一步应当查询哪一个域名服务器,本地域名服务器则继续查询下一个域名服务器,直到查询到被查询域名的权威域名服务器。迭代查询过程如下图所示
无论是递归解析还是迭代解析,在查询过程中,只要本地域名服务器不能直接响应解析结果,则都需要从根域名服务器开始查询。整个互联网上的根域名服务器数量有限,如果每次都去查询根域名服务器,则根域名服务器的压力很大,会严重影响查询响应时间和查询效率。所以需要一些策略和方案来改进域名系统的查询效率。
典型策略之一是域名服务器增加缓存机制,即在为客户做出响应的同时,每个域名服务器会将在域名解析过程中解析到的结果存储到域名数据库中,当再次收到相同域名信息的查询请求时,便可利用缓存的信息直接做查询响应,从而缩短域名查询响应时间。此外,还可以通过在本地域名服务器中存储顶级城名服务息,使得在域名解析过程中跳过根域名服务器的查询,直接查询顶级名服务器,提高域名查询效率。
四、万维网(WWW)
4.1、万维网应用结构
Web 应用主要包括 Web 服务器、浏览器与超文本传输协议(HTTP)等部分,如下图所示。
浏览器是 Web 应用的客户端软件,即 Web 应用的客户代理,运行在用户计算机上。Web 服务器是 Web 应用的服务器软件,存储并管理供用户请求浏览的 Web 页面(Web page)或称为 Web 文档。Web 应用是典型的客户/服务器网络应用,客户与服务器之间的交互基于应用层协议 HTTP。浏览器向 Web 服务器发送 HTTP 请求报文,服务器向浏览器送回HTTP 响应报文,其中包含客户所要的 Web页,浏览器对其中的Web页进行解析并显示。
Web 页面是由对象组成的。一个对象通常存储为一个文件,例如,HTML(超文本标记语言)文件、JPEG 图像文件、视频文件、Java 小程等。通常,多数 Web 页含有一个基本的 HTML页面,基本页中再引用若干其他对象。
在Web应用中,通过一个URL (Universal Resource Locator)地址来寻址一个Web页或Web对象,基本 Web 页也是通过 URL 地址引用其他对象。每个 URL 地址主要由两部分组成:存放对象的服务器主机域名(或IP 地址)和对象的路径名。例如,国内某大学计算机系的主页的 URL 地址为 http://www.abc.edu.cn/cs/index.html
、其中的www.abc.edu.cn
是Web 服务器主机名,/cs/index.html
就是路径名。URL 寻址方式确保万维网上的每个Web页或对象都有一个唯一的标识符。
4.2、HTTP
4.2.1、概述
HTTP是 Web 应用的应用层协议,定义浏览器如何向 Web 服务器发送请求以及 Web 服务器如何向浏览器进行响应。HTTP经历了多个版本的演变,目前主要使用的是 HTTP/1.0和HTTP/1.1两个版本,尤其以HTTP/1.1为主流。
HTTP在1991年发布的原型版本称为HTTP/0.9。该版本 HTTP 的设计初衷是为了获取简单的HIML对象,只支持GET方法,没有定义任何首部,不支持多媒体内容的 MIME 类型和协议版本号。正是由于设计缺陷,HTTP/0.9只在早期短时使用,很快被 HTTP/1.0所取代。
HTTP/1.0是第一个得到广泛应用的 HTTP 版本。HTTP/1.0增加了协议版本号、各种首部行、额外的方法以及对多媒体对象的支持。HTTP/1.0 使 Web 页面增添了生动的多媒体内容以及表单,增加了交互能力因此被人们广泛接受。但是,HTTP/1.0 的规范定义做得并不好。在20世纪90年代中期,很多流行的 Web 客户端和服务器都在向HTTP 中添加新的特性,以满足不同需求。其中很多特性,比如持久的keep-alive 连接、虚拟主机支持以及代理连接支持等,都被增加到 HTTP中,并成为非官方的事实标准。这种非正式的 HTTP/1.0扩展版本通常被称为HTTP/1.0+。
HTTP/1.0的新版本是 HTTP/1.1,是目前 Web应用最广泛的 HTTP版本。HTTP/1.1与HTTP/1.0相比,支持更多的请求方法、扩展了一些首部、增加了响应状态码、改进了对缓存的支持等。HTTP/1.1的重点是校正了HTTP设计中的结构缺陷,明确了语义,引入了重要的性能优化措施,并删除了一些不良特性。HTTP/1.1还包含了20世纪90年代末正在发展中的更复杂的Web应用程序部署方式的支持(如WebDAV),是目前使用的最主要版本。
最新版本的HTTP是 HTTP/2.0,但是该协议目前尚未得到广泛应用。HTTP/2.0最初称为 HTTP-NG, 是HTTP/1.1后继结构的原型建议,重点关注性能优化以及强大的服务逻辑远程执行框架。HTTP-NG 的研究工作终止于1998年。但是,后期某些技术的提出与发展还是推动了HTTP/2.0的探索与实践,其中最典型的就是 SPDY。SPDY (SPDY 是 Speedy 的昵音,意为更快)是Google开发的基于TCP的应用层协议。SPDY 协议的目标是优化HTTP的性能,通过压缩、多路复用和优先级等技术,缩短网页的加载时间并提高安全性。SPDY协议的核心思想是尽量减少TCP连接数,而对于HTTP的语义未做太大修改(例如,HTTP的 GET 和 POST 消息格式保持不变),基本上兼容 HTTP。SPDY 正是Google在HTTP即将从1.1向2.0过渡之际推出的协议,长期以来一直被认为是HTTP/2.0的可行选择。
4.2.2、HTTP连接
HTTP 基于传输层的 TCP 传输报文。浏览器在向服务器发送请求之前,首先需要建立TCP连接,然后才能发送 HTTP 请求报文,并接收HTTP响应报文。根据HTTP使用TCP连接的策略不同,可以分为非持久连接的HTTP和持久连接的HTTP。
4.2.2.1、非持久连接
非持久连接是指 HTTP 客户与 HTTP 服务器建立 TCP连接后,通过该连接发送 HTTP 请求报文,接收 HTTP 响应报文,然后断开连接。HTTP/1.0 默认使用非持久连接,每请求一个对象都需要新建立一个 TCP 连接。
为了对比非持久连接与持久连接的特点,下面通过一个例子来估算HTTP的响应时间。如下图所示。
假设用户在浏览器中输入了 URL地址http://www.abc.edu.cn/cs/index.html
,请求浏览一个引用了3个 JPEG 小图像的 Web 页面。如果基于HTTP/1.0,则从用户请求index.html 页面开始,到接收到完整的内容为止,整个请求传输过程是这样的:
-
HTTP 客户进程向服务器
www.abc.edu.cn
的80号端口(HTTP 服务器的默认端口),请求建立 TCP 连接。从客户进程发送连接请求,到收到服务器的连接确认,用时为1个往返时间(Round Trip Time, RTT)。显然,RTT并不是一个精确时间,而且每次的RTT可能是变化的,但在估算响应时间时可以作为一个时间单位来使用。 -
HTTP 客户进程基于已建立的 TCP 连接向服务器发送一个 HTTP 请求报文。请求报文中包含了路径名/cs/index.html。
-
HTTP 服务器进程接收该请求报文,从指定的路径中检索出index.html文件,并封到一个 HTTP 响应报文中,发送给客户进程。
-
HTTP 服务器程通知TCP断开该 TCP 连接。
-
hTTP客户接收响应报文,断开 TCP连接。浏览器从响应报文中提取出 HTML 文件,进行解析显示,并获知还有3个JPEG图片的引用。
-
对每个引用的JPEG图片,重复前4个步骤。
非持久连接的 HTTP1.0 协议每请求一个对象(Web 页或图像文件),都需要新建立一条 TCP 连接,对象传输结束,马上断开连接。如果忽略 HTTP 请求报文和响应报文的传输延时(即忽略报文长度),则 HTTP/1.0 使用非持久连接请求传输 Web 页以及3个 JPEG 小图像,共需要约8个RTT。另外,这种串行方式请求每个对象时,每次都要新建立 TCP 连接,因此都要经历TCP拥塞控制的慢启动阶段,使得 TCP 连接工作在较低的吞吐量状态,延迟会更加明显。
显然,为了提高或改善 HTTP的性能,需要对 HTTP/1.0 的这种默认的非持久连接使用方式进行优化,典型的优化技术包括以下两种:
- 并行连接,通过建立多条并行的TCP连接,并行发送 HTTP 请求和并行接收 HTTP 响应。
- 持久连接,重用已建立的TCP连接发送新的HTTP请求和接收 HTTP响应,从而消除新建 TCP 连接的时间开销。
4.2.2.2、并行连接
通过并行连接加速或优化HTTP是比较典型的技术手段,目前几乎所有的浏览器都支持并行连接,当然支持的并行连接数是有限制的。仍然以请求引用3个JPEG小图像的 Web 页为例,使用并行连接传输过程如下图所示。
当客户端接收到 Web 页后,可以并行建立3条TCP连接,然后分别利用一个连接请求一个JPEG 小图像,在忽略请求报文和响应报文长度的情况下,获取 Web 页以及3个JPEG小图像的总时间延迟约为4个RTT。可见,通常情况下,并行连接可以有效提高HTTP性能,减少 Web 页加载时间。
并行连接并不一定总能减小延迟,加快网页加载速度,例如,客户主机接入链路带宽受限。另外,并行连接会增加客户端主机的资源开销,如内存开销,因此系统通常对同时建立的并行TCP连接数有限制。同样,服务器通常也会对来自同一客户的并行TCP连接数有所限制。
4.2.2.3、持久连接
客户端请求了 Web 页后,继续传输引用的图像文件,这些图像文件多数情况下位于Web 页所在的服务器,即具有站点局部性特点。这种情况下,可以不断开已建立的 TCP连接,而是利用该连接继续请求后续的 JPEG 小图像,这种 TCP 连接称为持久连接。
根据使用持久连接传输多个对象的策略不同,持久连接又分为两种工作方式:非流水方式持久连接和流水方式持久连接。
-
非流水方式持久连接:也称为非管道方式持久连接,客户端在通过持久连接收到响应报文后,才能发出对下一个对象的请求报文。与非持久连接相比,连续请求多个对象时(例如,Web 页内引用多个图像),只需建立一次 TCP 连接,这样,每获取一个对象只需1个RTT 时间。
-
流水方式持久连:也称为管道方式持久连接,客户端在通过持久连接收到前一个对象的响应报文之前,连续依次发送对后续对象的请求报文,然后再通过该连接依次接收务器发回的响应报文。使用流水方式持久连接时,获取一个对象平均时间远小于1个 RTT 时间,如果忽略对象传输时间,连续请求的多个对象只需1个RTT时间。
使用非流水方式持久连接请求传输引用3个 JPEG小图像的 Web 页过程如下图(a)所示,传输所有对象需要的总时间约为5个RTT。使用流水方式持久连接请求传输引用3个JPEG小图像的Web页的传输过程如下图(b)所示,总时间需求约为3个RTT。
HTTP/1.1 默认情况下使用流水方式持久连接。HTTP/1.1 的持久连接默认是激活的,除非特别声明,否则 HTTP/1.1 假定所有连接均是持久的。如果希望结束持久连接,可以在报文中显式地添加connection: close 首部行。也就是说,HTTP/1.1客户端在收到的响应报文中没有包含 connection: close首部行,则继续维持连接为打开状态。当然,不在响应报文中发送connection: close 首部,并不意味着服务器就承诺永久将连接保持在打开状态,比如超过一定时间,就可能主动关闭。HTTP/1.1使用持久连接的主要约束与规则如下。
-
如果客户端不期望在连接上发送其他请求,则应该在最后一条请求报文中包含connection: close首部行。
-
如果客户端在收到的响应报文中包含connection: close首部行,则客户端不能继续在这条连接上发送更多的请求。
-
每个持久连接只适用于一跳传输,HTTP/1.1代理必须能够分别管理与客户端和服器的持久连接。
-
HTTP/1.1代理服务器不应该与HTTP/1.0客户端建立持久连接。
4.2.3、HTTP报文
4.2.3.1、组成
HTTP报文由 4 部分组成:起始行(start line)、首部行(header lines)、空白行(blank line)和实体主体(entity body)。
起始行与首部行是行分隔的 ASCII 文本,每行由 CRLF(回车换行)终止,空白行中只有 CRLF,实体主体(或称报文主体)可以是文本或二进制数据。HTTP 报文起始行和空白行不可缺少,首部行可以是零行或多行,实体主体则根据报文类型、功能等可有可无。
4.2.3.2、分类
HTTP报文可以分为两类:请求报文和响应报文,请求报文由浏览器(客户端)发送给Web服务器,响应报文由Web服务器发送给浏览器。请求报文和响应报文的结构如下图所示。
请求报文与响应报文最主要的区别是起始行不同,请求报文起始行是<方法> <URL> <协议版本>
,响应报文起始行是<协议版本> <状态码> <短语>
。
4.2.3.3、请求报文
HTTP请求报文的起始行也称为请求行。请求行中的“方法”实际上就是命令,表示客户端希望服务器对 URL 指定的资源执行的操作(或动作),即表示希望服务器做什么;URL定位所请求的资源;协议版本用于通告服务器客户端所使用的 HTTP 版本号,格式为:HTTP/<主版本号>.<次版本号>
,目前典型的版本是HTTP/1.0和HTTP/1.1。请求行中的方法、URL和协议版本由空格分隔,最后是CRLF。
HTTP典型的请求方法有GET、HEAD、POST、OPTION、PUT等。其中:
- GET:请求读取由URL 所标识的信息,是最常见的方法。
- HEAD:请求读取由URL所标识的信息的首部,即无须在响应报文中包含对象。
- POST:给服务器添加信息(例如,注释) 。
- OPTION:请求一些选项的信息。
- PUT:在指明的URL下存储一个文档。
HTTP 报文的首部行用于携带附加信息,可以是零行、一行或者多行。每个首部行包括一个首部行字段名,后面跟一个冒号(:),然后是一个可选的空格,紧接着是对应的值,直后是CRLF。不同首部行携带不同类别信息,用于不同目的。有些首部行只能用于请求报文,称为请求首部;有些首部行只能用于响应报文,称为响应首部;有些首部行既可用于请求报文又可用于响应报文,称为通用首部;有些首部专门用于描述实体相关属性信息(称为实体首部),例加实体长度;除此之外,还有一些由应用程序开发人员创建,尚未添加到HTTP规范中的非标准专用首部,称为扩展首部。
首部行结束后,必须有一个空白行,用于分隔首部行(或请求行)与实体主休。
实体主体也称为报文主体或称为主体,是请求报文的负荷,可以是文本、图片、视频、HTML文档、应用程序、电子邮件等。有些请求报文会带主体,有些不带主体(可能很多求报文不带主体)。
4.2.3.4、响应报文
HTTP 响应报文中的起始行也称为状态行。其中的协议版本与请求报文中的协议版本意义与格式相同,用于声明服务器所用的HTTP版本号;状态码用于向客户端通告对请求的响应情况,由3位十进制数组成,不同状态码具有不同含义;短语是对状态码的进一步文本解释,只对人类有意义,对于相同的状态码,即便短语不同,协议的解释与处理结果是相同的。响应报文中首部行、实体等的格式与作用和请求报文相同。另外,响应报文也不一定都携带实体。
状态码用于服务器向客户端通告响应情况。客户端向 HTTP 服务器发送请求时,可能发生很多种情况,可能成功完成,可能出错,也可能需要转移请求等。HTTP 响应报文的状态码就是用于向客户端通告响应情况,HTTP 客户端在收到响应报文时,将根据该状态码判断服务器对请求的响应情况,以及决策如何处理该响应报文等。HTTP状态码由3位十进制组成,并利用第一位十进制数字区分为5类状态码,HTTP状态码的分类如下表所示。
状态码类别 | 取值范围 | 作用 | 说明 |
---|---|---|---|
1xx | 100~199 | 信息提示 | 通告信息,可能还需要进一步交互 |
2xx | 200~299 | 成功 | 成功完成客户请求的操作,并进行响应 |
3xx | 300~399 | 重定向 | 表示资源已移走,需要向新URL发请求 |
4xx | 400~499 | 客户端错误 | 由于客户端请求错误,无法成功响应 |
5xx | 500~599 | 服务器端错误 | 由于服务器端错误,无法成功响应 |
当前的 HTTP版本对每类状态码只定义了几个代码。如果收到了超出当前协议版本定义的状态码范围(可能是人为扩展),则作为对应类别的普通状态码处理。常见的HTTP状态码如下表所示。
状态码 | 短语 | 含义 |
---|---|---|
100 | Continue | 表示已成功收到了请求的初始部分,请客户端继续 |
200 | OK | 成功,所请求信息在响应报文中 |
301 | Moved Permanently | 重定向,所请求对象被永久移走,响应报文的首部行Location会给出新的URL,通常浏览器会自动再向新URL发送请求 |
400 | Bad Request | 客户端请求错误,即服务器不能正确理解客户请求 |
401 | Unauthorized | 未授权,需要输入用户名和密码 |
404 | Not Found | 客户端请求的对象,在服务器上不存在 |
451 | Unsupported Media Type | 不支持的媒体类型,可能被服务器拒绝请求,或者是请求方法或参数与服务器要求不匹配 |
505 | HTTP Version Not Supported | 请求使用的HTTP版本,服务器不支持 |
4.3、Cookie
4.3.1、Why
HTTP是无状态协(stateless protocol)。HTTP 服务器在向客户发送被请求的文件后,不保存任何关于该客户的状态信息。假如某个客户在短时间内连续两次请求同一个对象,HTTP 服务器并不会因为刚刚为该客户提供了该对象就不再做出响应,而是重新发送该对象,就像服务器已经完全忘记不久之前所做过的事一样。因为HTTP服务器并不保存关于客户的任何信息。
由于HTTP是一种无状态的协议,因此,客户与服务器之间一旦数据交换完毕,客户端和服务器端的连接就会关闭,再次进行数据交换时需要建立新的连接,这就意味着服务器端无法跟踪用户的会话。比如,用户每次登录论坛、社交网网网站时,都需要重新输入用户名和密码;用户进行网络购物时,选购了一件商品放入购物车内,当再次选择其他商品时,服务器无法识别该次购物是否还是这位顾客的行为,因此需要每购买一件商品就立即结账。为了解决这些问题,Web应用引了 Cookie 机制,用于用户跟踪。
4.3.2、What
Cookie 最早是网景公司的前雇员 Lou Montulli在1993年3月发明的。
Cookie中文名称为小型文本文件,指某些网站为了辨别用户身份、进行会话跟踪而储存在用户本地终端上的数据。
Cookie是由服务器端生成,发送给 User-Agent(一般是浏览器),浏览器会将 Cookie 的key/value 保存到某个目录下的文本文件内,下次请求网站时就发送该Cookie 给服务器(前提是浏览器设置为启用 Cookie)。目前,主流的商业网站均使用Cookie 技术。
Cookie 技术主要包括4部分内容。
-
HTTP 响应报文中的 Cookie 头行:Set-Cookie。使用Cookie技术的网站,在给用户发送的 HTTP 响应报文中,通过 Set-Cookie头行,发送大小通常不超过4KB的Cookie 息,包括为其用户分配的ID、用户对网站的访问偏好等。
-
用户浏览器在本地存储、维护和管理的 Cookie 文件。浏览器每当获得新的 Cookie 信息,便会在 Cookie 文件中追加一行Cookie 信息,包括网站的域、路径、内容(如用户ID、访问偏好、商品选择等)、有效期和安全5个字段。
-
HTTP 请求报文中的 Cookie 头行:Cookie。当用户向已经访问过且已经获得 Cookie 信息的网站发送 HTTP 请求报文时,浏览器会自动检索本地的 Cookie 文件,并在每个请求报文中通过 Cookie头行,携带上网站为该用户分配的 Cookie 信息。网站可以基于用户请报文中的Cookie,实现对用户的跟踪、偏好统计、会话关联等功能。
-
网站在后台数据库中存储、维护 Cookie信息,包括已分配给用户ID、每个ID用户在本网站的访问特征等。
4.3.3、How
Cookie的基本工作原理如下图所示。
假设某用户以前访问过亚马逊(Amazon.com)网站,现在第一次使用 IE 浏览器上淘宝网。此时,该用户的Cookie 文件中没有存储与淘宝网相关的 Cookie 数据,因此浏览器向淘宝服务器发送普通HTTP请求报文,当请求报文到达该淘宝 Web 服务器时,该 Web 站点将为该用户创建一个唯一ID识别码 56789,并以此作为索引在服务器的后端数据库中产生一个表项。
接下来,淘宝 Web 服务器向该用户的浏览器发送 HTTP 响应报文,其中包含 Set-Cookie: 56789 首部,将网站为该用户分配的 ID 发送给用户浏览器。
浏览器收到响应报文从 Set-Cookie: 56789 首部中解析到网站为其分配的 Cookie ID,于是浏览器在其管理的Cookie 文件中增加关于淘宝网的 Cookie 信息,包括淘宝网的主机名、ID等。
当该用户继续浏览淘宝网或者过一段时间再次访问淘宝网时,浏览器会从该 Cookie 文件中获取淘宝网为其分配的ID识别码,并在每个发送给淘宝 Web 服务器的 HTTP 请求报文中增加Cookie: 56789 首部行。
当淘宝 Web 服务器收到包含首部行 Cookie: 56789 的请求报文后,提取该用户ID,检索数据库获取该用户在本网站上的以往活动信息,并对该用户的每次访问进行跟踪。
进一步,Web 服务器可以根据对该用户的跟踪,做出有针对性的响应,比如发送含有针对性广告的Web页面等。
4.3.4、How Good
Cookie 可以实现在无状态的 HTTP之上建立用户会话。例如,当用户向一个基于Web 的电子邮件系统(如Hotmail)注册时,浏览器向服务器发送 Cookie 信息,允许该服务器在用户与应用程序会话的过程中标识该用户,从而跟踪整个会话过程中对邮箱中邮件的操作。
Cookie 文件可以保存在客户端计算机的硬盘中,也可以保存在客户端计算机的内存中。保存在硬盘中的 Cookie通常被称为永久 Cookie,Cookie的有效周期可以进行设置,关闭览器不影响 Cookie 的有效周期。保存在内存中的 Cookie 被称为会话 Cookie,表示这个Cookie的有效周期是浏览器的会话期间,只要关闭浏览器窗口, Cookie 就会消失。
Web网站利用Cookie 技术进行用户跟踪,最常见的用途包括以下几点。
-
网站可以利用 Cookie 的ID来准确统计网站的实际访问人数、新访问者和重复访者的人数对比、访问者的访问频率等数据。
-
网站可以利用 Cookie 限制某些特定用户的访问。
-
网站可以存储用户访问过程中的操作习惯和偏好,对不同的用户呈现不同的显示内容、颜色、布局等界面元素,有针对性地为用户提供服务,提升用户体验感。
-
记录用户登录网站使用的用户名、密码等信息,当用户多次登录时,无须每次都从键盘输入这些繁琐的字符和数字。
-
电子商务网站利用 Cookie 可以实现“购物车”功能。对于同一个ID的用户,网站可以跟踪其向“购物车”中添加的不同商品,每个商品都会和 ID一起存储在网站数据库中。当用户选择结账时,网站通过对数据库中该ID的检索,找到用户购买的所有商品,一起实现结账功能。
Cookie 技术使万维网的使用更加方便,但也带来一定的安全问题。例如,网站利用Cookie 跟踪每个用户的访问行为、账户、密码等信息,一旦泄露,会给用户造成很大的损失;对于在公共场所多个用户使用同一台计算机的情况,使用 Cookie 可能会暴露某个用户的网络操作行为,如登录过哪些网站、购买过哪些商品等信息。
如果在一台计算机中安装多个浏览器,每个浏览器都会以独立的空间存放 Cookie,因为Cookie 中可以确认用户,还能包含计算机和浏览器的信息,所以一个用户用不同的浏览器登录或者用不同的计算机登录,都会得到不同的 Cookie 信息。另一方面,对于在同一台计算机上使用同一浏览器的多用户群,Cookie 不会区分他们的身份,除非他们使用不同的用户名登录。
五、Internet电子邮件
电子邮件是最早在Internet上流行起来的网络应用之一,可实现用户之间电子化邮件的异步传输 。电子邮件系统主要包括邮件服务器、简单邮件传输协议(SMTP)、用户代理和邮件读取协议等。
邮件服务器的功能是发送和接收邮件,同时还要向发信人报告邮件传送的情况(已交付、被拒绝、丢失等),是电子邮件体系结构的核心。
邮件服务器为每个注册用户创建一个邮箱,存放该用户接收到的邮件,管理一个外出邮队列,并从队列中取出邮件进行发送。每个用户的邮箱都有一个唯一的电子邮件地址,格式为:收件人邮箱名@邮箱所在主机的域名(或IP地址),其中符号“@“读作"at”,表示“在”的意思。
SMTP是Internet电子邮件中核心应用层协议,实现邮件服务器到邮件服务器之间或用户代理到邮件服务器之间的邮件传输。
SMTP使用传输层 TCP,在SMTP客户与服务器(默认25号端口)之间建立 TCP连接后,经历握手阶段、邮件发送阶段和关闭阶段,完成邮件传送。
SMTP只能传输7位ASCII码文本内容,如果传输非7位ASCII 码文本内容,需要根据 MIME 将非7位ASCII 码文本内容编码转换为7位ASCII码文本内容,然后再通过 SMTP 进行传输。
SMTP是“推动”协议,发送邮件的服务器(或代理)主动请求与接收邮件的邮件服务器建立连接,然后将邮件发送过去。
当用户需要访问自己的邮箱,读取其中的邮件时,所使用的应用层协议是邮件读取协议。邮件读取服务器的主要作用是用户身份鉴别(需要登录用户名和密码)、访问用户邮箱、根据用户请求对邮箱中的邮件进行操作等。目前,邮件读取协议包括 POP3(第三版的邮局协议)、IMAP(互联网邮件访问协议)和HTTP,其HTTP是Web 邮件系统的邮件读取协议。
六、FTP
文件传送协议(FTP)是在互联网的两个主机间实现文件互传的网络应用。FTP使用传输层TCP。
FTP客户与服务器(21号端口)建立一条TCP 连接,称为控制连接,用于传输命令。控制连接是持久的。在传输文件等数据时,客户与服务器的20号端口之间建立一条临时的 TCP 连接,用于传输数据,数据传输结束便断开连接,该连接称为数据连接。FTP 这种使用两条TCP连接分别传输控制命令与数据的方式,称为带外控制。另外,FTP是有状态的协议。
七、P2P应用
基于客户/服务器体系结构的应用,它们要求有总是在运行着的基础设施服务器,如DNS服务器、万维网服务器、邮件服务器等。与这些应用不同,基于P2P体系结构的应用是对等方之间直接进行通信,而且对等方主要运行于间断连接的主机上,如个人计算机,而不是运行于24h连续开机的服务器上。
目前,在互联网上流行的P2P应用主要包括P2P文件共享、即时通信、P2P流媒体、分布式存储等。在这里我们仅以P2P文件共享为例来简单介绍P2P的应用。文件共享应用实际上有两个基本的问题要解决:如何查找到你需要的文件,以及如何从拥有该文件的主机下载该文件。这里我们仅讨论后一个问题,即P2P文件分发(从文件拥有者角度看是将一个文件分发给多个对等方)。
7.1、P2P文件分发
我们通过一个简单的例子来说明P2P方式在文件分发应用中的优势。该任务是将主机H1 中的一个长度为L 的大文件分发给其余七台主机。假设文件传输的瓶颈是各主机的上载速率,再假定所有主机的上载速率都是R 。对于客户/服务器方式,主机H1 为服务器,而其他主机为客户。显然主机H1 要依次把文件发送给所有其他主机,所需的时间是7L /R 。可见采用客户/服务器方式,文件分发时间随客户机的数量呈线性增长。因此,基于客户/服务器方式的应用在面对大量用户访问时,服务器要承受极大的负担,并且消耗大量的服务器带宽。
在P2P文件分发中,每个对等方都能在收到文件后再将该文件分发给其余对等方,从而协助主机H1 进行分发,这样就大大缩短了文件分发的时间。例如,可以在3L /R 时间内就把长度为L 的文件分发给所有七台主机:
-
第1个L /R 时间,H1 →H2 ;
-
第2个L /R 时间,H1 →H3 ,H2 →H4 ;
-
第3个L /R 时间,H1 →H5 ,H2 →H6 ,H3 →H7 ,H4 →H8 。
可以证明采用这种基本的P2P分发方式,文件分发时间随对等方数量呈对数增长。显然,每个对等方都参与了文件的分发,它们既是服务的请求者,也是服务的提供者。参加的对等方越多,服务的提供者也就越多。因此,P2P方式比客户/服务器方式具有更好的可扩展性。
实际上,通过分片 ,即把文件划分为很多等长的小数据块进行分发,可以进一步加快文件分发的速度。因为一个对等方不必等整个文件全部收完就可以将该文件的部分数据块分发给其余对等方,这提高了文件分发的并行性。这就是说,对每一台需要下载文件的主机来说,不仅可以从多个对等方下载数据块,而且可以同时给多个对等方上载数据块。下图说明了这种情况。可以看出,数据块的传送途径不仅有A→B,A→C,A→D,而且有B→C,B→D,C→B,C→D,D→B,D→C。
巧妙地设计分发算法可以大大提高整个系统文件分发的效率。在一个实际的P2P文件分发系统中,任意两个拥有不同数据块的对等方之间都可能互相传送数据块,并且不断有对等方加入或离开。下载某个文件的人越多,拥有该文件数据块的对等方就越多,新加入的对等方就可以从更多的对等方下载该文件,因此有可能更快地下载完整的大文件。这就是为什么使用P2P文件分发软件的用户会有“下载的人越多,下载速度越快”的体验。由于对等方随时都有可能离开,为避免所有下载同一文件的对等方都缺少同一数据块,对等方通常会优先下载“稀有”数据块(拥有该数据块的对等方少),因此每个文件的数据块下载顺序具有随机性。
7.2、文件分发时间分析
下面通过对比文件分发应用的客户/服务器实现与 P2P 实现,来展示P2P 应用的优势。
假设网络上有n个用户(即 C/S应用中的客户, P2P应用中的对等方),都期望得到文件F的一份副本。文件分发应用就是实现每个用户都获得文件F的一个副本的过程。这一应用场景在网络上是非常常见的,比如,很多用户都想下载一个开源的软件,或者都想下载一个MP3音乐文件等。显然,文件分发既可以通过客户 / 服务器体系结构的网络应用来实现,又可以通过 P2P 体系结构网络应用来实现。
下面通过分析分发时间的下界,来对比两种应用的实现。文件分发问题的示意图如下图所示,其中,为服务器接入网络链路的上行带宽;()为第i个用户主机接入网络链路的上行带宽;()为第i个用户主机接入网络链路的下行带宽。另外,假设互联网带宽足够大,即忽略互联网的数据传输时间,并假设服务器和客户没有参与任何其他网络应用,因此它们的所有上行和下行接入带宽被全部用于分发文件。
首先分析采用客户/服务器体系结构实现文件分发的时间。在客户/服务器体系结构中,每个客户都需要请求服务器为其发送—个文件副本,因此,服务器的上传数据总量为 nF,所需时间至少为 。另外,令表示具有最小下行带宽的客户的下行带宽,即,则具最下行速率的客户不可能在少于时间内获得文件F。时间和可以近似看做是并行发生的,于是,采用客户/服务器体系结构实现文件分发的最小分发时间至少为
上式为采用客户/服务器体系结构实现文件分发的最小分发时间的下界,可以看做文件分发的最快时间。显然,在F,和一定的前提下,这个时间随n的增加而线性增加,当n大于某个阈值后,便取决于n的大小,n越大,所需的最快时间也越大。
接下来,再分析一下采用 P2P 体系结构实现文件分发的时间。在P2P 体系结构中,每个对等方在接收到文件的部分数据后,马上可以将其拥有的数据向其他对等方分发,即每个对等方既是数据的需求方,又是数据的提供方。每个对等方获得的文件F的完整数据,大部分都来自于其他对等方。当然,由于文件分发之初只有服务器上有文件F, 所以理想情况下,服务器只需要上传1份F,用时为。类似地,具有最小下行速率的对等方获得1份文件F的时间不少于。n个客户共获取 n 份文件F,总数据量 nF,理想情况下,这些数据是由服务器和所有的对等方共同上传的,至少用时
因此,采用P2P体系结构实现文件分发的最快时间为
上式为 P2P 体系结构实现文件分发的最小分发时间的下界。特别地, 如果,则上式可以写成
从上式可以很直观看到,在这种条件下,P2P 体系结构实现文件分发的最快时间几乎不会随着对等方数量的增加而显著增加,当n足够大时,趋近于一个常量。
通过以上分发时间的分析与对比可以看出,在实现文件分发这一应用场景中, P2P 体系结构应用远远优于客户/服务器体系结构应用。究其原因,主要是在 P2P 应用中,每个对等方即是数据的获取者(消费者)又是数据的提供者(服务器)。P2P 应用充分聚集和利用了每对等方接入链路的上行带宽以及每个对等方的处理能力。这正是大部分 P2P 应用的理念:“人人为我,我为人人”。也正是P2P在文件分,文件共享等类应用中表现的优异性能,所以近年来P2P应用大量出现,并深得用户喜爱。
八、Socket编程基础
网络应用进程可以创建3种类型的Socket:数据报类型套接字 SOCK_DGRAM、流式套接字 SOCK_STREAM和原始套接字 SOCK_RAW。其中,SOCK_DGRAM面向传输层 UDP 接口;SOCK_STREAM面向传输层 TCP接口;SOCK_RAW 面向网络层协议(如IP、ICMP 等)接口。
基于TCP客户与服务器的典型Socket API函数调用过程如下:
-
服务器程序运行后,调用 socket()函数创建 SOCK_STREAM类型的主套接字ms;调用 bind()函数绑定本地端点地址;调用listen()函数置主套接字ms为监听模式;调用accept ( ) 函数通过主套接字ms接收客户连接请求,并阻塞服务器讲程,直到有客户连接请求到,accept()函数调用成功,返回(创建)连接套接字ss。
-
客户程序在服务器程序运行后执行,创建了本地 SOCK_STREAM类型的套接字cs后,调用connect()函数请求与服务器建立 TCP连接,connect()函数调用成功,表明 TCP 连接建立成功。接下来,客户程序与服务器程序通过调用 send()函数和 recv()函数,实现数据发送与接收。通信结束后,客户程序通过调用 close()函数,释放套接字 cs;服务器程序通过调用close()函数,释放套接字ss,从而关闭TCP连接。服务器程序继续调用accept()函数,通过主套接字ms接收下个客户连接请求。
-
服务器端在调用 accept()函数时,通常阻塞服务器进程,等待客户的连接请求,一旦有客户连接请求到达,accept()函数会返回(创建)一个新的套接字 ss, ss 是真正与客户建立 TCP连接的。服务器与客户的通信是通过与特定客户连接ss进行的,当与该客户通信结束后,可调用close()函数关闭与客户通信的 ss。服务器通常通过无限循环机制,继续调用accept()函数继续等待新的客户连接请求,周而复始。
基于UDP客户与服务器的典型Socket API函数调用过程为:服务器程序运行后,调用 socket()函数创建 SOCK_DGRAM类型的套接字ums;调用bind()函数绑定本地端点地址。客户程序运行后,创建本地SOCK_DGRAM类型的套接ucs。接下来,客户程序与服务器程序通过调用 sendto()和recvfrom()函数,实现数据发送与接收。通信结束后,客户程序通过调用 close ()函数,释放套接字 ucs;服务器程序继续调recvfrom()函数,通过套接字ums接收下一个客户发送过来的数据报。