第七章 应用层

应用层是原理体系结构中的最高层,其重要特点就是自身的可扩张性。本章讨论各种应用进程通过什么样的应用层协议来使用网络所提供的通信服务。
  概述
  域名系统
  电子邮件
  远程登录
  文件传输与访问
  USENET新闻
  万维网WWW

第一节 概述
应用层是OSI体系结构中的最高层,一个重要特点就是自身的可扩展性。
每个应用层协议都是为了解决某一类应用问题。
应用进程:为了解决具体应用问题而彼此通信的进程。
具体内容:规定本进程在通信时所遵循的协议。
应用进程之间通信时所使用的协议:
一部分是标准化的应用层协议;
在此之上,还有一些为了满足特定的应用需求而制定的非标准化协议。
应用软件:为用户提供高层服务,并决定用户对基础互联网能力的理解方式。
互联网系统提供基础的通信服务,除协议软件外,通信中必须有两个应用程序参加:
一个启动通信;
另一个接受它。
7.1.1 客户—服务器交互——网络应用程序使用的通信方式,描述进程之
间服务和被服务的关系。
主要特征:客户应用程序是主叫方,主动地启动通信;服务器应用程序是被叫方,被动地等待通信。
客户端软件的一般特性:
是一个任意的应用程序,在需要进行远程访问时临时成为客户,同时也做其他的本地计算;
直接被用户调用,只运行一次;
在用户的个人计算机上本地运行;
主动地与服务器启动通信;
能支持所需的多重服务,但同时只与一个远程服务器进行主动通信;
不需要特殊的硬件和高级的操作系统。
服务器软件的一般特性:
有专门用途,享有特权,专门用来提供某种服务,可同时处理多个远程客户的请求;
在系统初启时自动调用,不断运行许多遍;
在一台共享计算机上运行(即:不是在用户的个人计算机上);
被动地等待来自任意客户的通信;
接受来自任意客户的通信,但只提供一种服务;
需要强大的硬件和高级的操作系统支持。
客户与服务器的通信可以是双向的,都可以发送和接收信息。
大多数应用进程都使用TCP/IP协议进行通信。
客户与服务器的交互直接通过传输协议建立通信和收发信息;
传输协议接着使用更低层的协议来收发自己的信息。
一台计算机无论运行客户程序还是服务器程序,都需要一个完整的协议栈。

功能较强的计算机系统同时运行多个客户与服务器程序的条件:
首先,这台计算机必须具有足够的硬件资源;
其次,这台计算机必须具有允许多个应用程序同时执行的操作系统。
在服务器系统上,对应每种服务有一个服务器程序在运行,并有唯一标识。
例如:计算机1和计算机2中的客户进程分别和计算机3中的两个服务器进程进行通信。
单机运行多重服务,通过TCP的复用技术只需有一个物理连接。

7.1.2 套接字接口
客户与服务器应用程序使用传输协议进行通信!
应用程序与协议软件进行交互时必须说明一些细节:
应用程序:是服务器还是客户(即它是被动等待还是主动启动通信);
发送方:必须说明数据将传给谁;
接收方:必须说明接收的数据应从何处获得,等等。
应用程序接口(API):应用程序与操作系统中通信协议之间的接口。
一个API定义了一组操作,应用程序在进行交互时可以对API进行操作;
API决定了应用程序所能达到的功能,以及使用这些功能开发程序的难度;
大多数API给出一组应用程序能够调用的过程以及过程参数;
通常一个API对每个基本操作有一个独立的过程,例如:一个API包含两个过程,一个用来建立通信,另一个用来接收数据。
通信协议通常只定义协议应当提供的一般操作;
操作系统定义应用程序用来完成这些操作的API规范。
套接字API——被众多操作系统支持,包括个人机操作系统及各种UNIX系统。
套接字库(socket library):提供套接字API,目的是广泛使用套接字而不修改基本操作系统。
从程序员角度看,套接字库与操作系统提供的本机套接字在语义上是相同的!
一个使用套接字的程序可以被复制到一台使用套接字库的计算机上,经过重新编译后执行,移植时无须改动。
套接字库与由操作系统直接提供的本机套接字API在实现上是完全不同的!
本机套接字API是操作系统的一部分;
套接字库的过程代码是链接到应用程序并驻留于应用程序地址空间的。
当应用程序从套接字库调用过程时,控制转向库例程,库例程接着进行一个或多个对基本操作系统函数的调用来达到希望的效果。
基本操作系统支持的函数不需要与套接字API相匹配,套接字库例程对应用程序隐蔽了本机操作系统而只给出了一个套接字接口。
套接字库能够向没有本机套接字的计算机上的应用程序提供套接字API!
当应用程序调用套接字过程时,控制转向库例程,由它进行一个或多个对基本操作系统的调用来完成套接字功能。
由于起源于UNIX,套接字使用了UNIX其他部分的许多概念;
套接字与I/O紧密相连:应用程序通过套接字进行通信和应用程序与文件进行数据交换是相似的。
套接字通信使用描述符方法:当应用程序创建一个套接字时,它会得到一个标识(短整型数)来指向该套接字。
过程:应用程序在使用协议进行通信前,须申请操作系统生成一个套接字用以通信系统返回一个短整型数作为描述符来标识这个套接字应用程序在调用过程通过网络传输数据时,将这个描述符作为参数,不必在每次传输数据时都指明远程目的地的细节。
套接字与其它I/O集成在一起:系统对套接字和其他I/O设备使用相同的描述符空间。
集成系统的主要优点:在于灵活性,一个单独的应用程序可以写成向任意方向(设备、文件、套接字)传输数据,既用于网络通信又用于本地数据传输。
套接字编程与传统I/O编程有所不同:应用程序要使用套接字则必须说明许多细节,每个套接字有许多参数与选项以提供所有这些细节,应用程序支持这些选项的每个取值。
例如:应用程序必须选择特定的传输协议,向协议提供远程机器的地址,并说明该应用程序是客户还是服务器。
选项与参数在一个API中的表达:应用程序首先创建一个套接字,然后用调用函数来说明套接字被使用的细节。
为避免单个套接字函数对每个选项有不同的参数,须定义多个函数。
优点:大多数函数只有三个或更少的参数,
缺点:编程者在使用套接字时必须记住要调用多个函数。
创建一个套接字时,应用程序必须说明使用的协议族以及所希望的服务类型(面向连接的或无连接的)。
服务器在创建套接字后,向该套接字说明一个本地地址及请求队列的大小。
客户在创建套接字后,向该套接字说明远程服务器的地址。
一个套接字建立以后,应用程序就可以传输信息!
用于发送信息的基本过程是send,send有多种形式,应按照服务所需的类型选择合适的过程。
用于接收信息的基本过程是recv,recv也有对应于send的多种形式。

过程名
参数说明
功能说明
Socket
(protofamily,
type,protocol)
protofamily:套接字使用的协议族 type:套接字使用的通信类型 protocol:套接字使用的特定传输协议 socket系统根据需要创建套接字,并返回一个整型描述符。
close(socket) socket:要关闭的套接字描述符 终止对使用一个套接字,释放描述符。
bind(socket,
localaddr,
addrlen)
socket:要绑定的套接字描述符 localaddr:指定套接字要绑定的本地地址结构 addrlen:指定地址长度的整数 提供一个协议端口号,服务器将通过它等待通信。
listen(socket,
queuesize)
socket:已绑定的套接字描述符 queuesize:该套接字的请求队列的长度 将该套接字设为被动模式,以使它能用来等待客户的通信。
accept(socket,
caddress,
caddresslen)
socket:服务器已经创建并绑定到指定协议端口的套接字描述符 caddress:建立连接的客户地址 caddresslen:指向整型数(地址的长度)的指针 使用面向连接传输协议的服务器调用accept过程来接受下一个连接请求,并返回给调用者一个新的套接字。
connect(socket,
saddress,
saddresslen)
socket:客户端计算机上用于该连接的套接字的描述符 saddress:说明服务器地址与协议端口号 saddresslen:以8位组表示的服务器地址长度 客户使用该过程与指定的服务器建立连接,即将套接字连接到目的地址。

套接字API应设计成适应于并发程序工作。
新线程被创建后,继承创建它的线程所拥有的所有套接字的访问权;
一个并发服务器首先打开一个套接字用以接受请求;
系统在连接请求到达时接着创建一个新的套接字;
主线程关闭这个新套接字而新线程关闭旧套接字。
客户与服务器对套接字过程调用的顺序。
如图所示,服务器调用了7个套接字过程而客户调用了6个。