本章首先介绍Socket API的概念,接着详细阐述了数据Socket和流式Socket的区别和编程方法,然后讨论客户/服务器范型的基本概念和实现,接着重点介绍基于三层软件的客户/服务器应用开发方法,然后给出客户/服务器中服务的三种分类及开发技术----面向连接与无连接服务器程序、迭代与并发服务器程序、有序与无序状态服务器程序。
Socket概述与分类
Socket API最早作为Berkeley UNIX 操作系统的程序库,出现于20世纪80年代早期,用于提供IPC功能。现在主流操作系统都支持Socket API。在BSD、Linux等基于UNIX的操作系统中,Socket API 都是操作系统的一部分。在个人计算机操作系统(如MS-DOS、Windows NT、Mac-OS、OS/2)中,Socket API 都是以程序库形式提供的(在Windows系统中,Socket API 称为 Winsocket)。Java语言在设计之初就考虑到了网络编程,也将Socket API 作为语言核心类的一部分提供给用户。所有这些 API 都使用相同的消息传递模型和非常类似的语法。
Socket API 是实现进程间通信的第一种编程设施。Socket API 非常重要,原因主要有以下两点:
- Socket API 已经成为 IPC 编程事实上的标准,高层 IPC 设施都是构建于 Socket API 之上的,即基于 Socket API 实现。
- 对于响应时间要求较高或在有限资源平台上运行的应用来说,用 Socket API 实现是最合适的。
数据包Socket API
数据包 Socket 在应用层可以支持无连接通信及面向连接通信。这是因为,尽管数据包在传输层发送和接收时没有连接信息,但 Socket API 的运行时支持可以为进程间的数据包交换创建和维护连接。无连接数据包 Socket 和面向连接数据包 Socket 的比较如下图。
Java为数据包Socket API提供了两个类:针对Socket的DatagramSocket类和针对数据包交换的DatagramPacket类。
使用该API发送和接收数据的进程必须实例化一个DatagramSocket对象,或简称为Socket对象。每个Socket被绑定到该进程所在机器的某一个UDP端口上。
为向其他进程发送数据包,发送者进程需要实现下列步骤:
- 创建一个代表数据包本身的对象。该对象可通过实例化一个携带下列信息的DatagramPacket对象来创建:
- 一个包含有效数据的字节数组引用。
- 目标地址(接受者进程的Socket所绑定的主机ID和端口号。)
- 调用DatagramSocket对象的send方法,将DatagramPacket对象引用作为传递参数
在接收者进程中,需要实现如下步骤:
- 实例化一个DatagramSocket对象并将其绑定到一个本地端口上,该端口必须与发送者数据包当中定义的一致。
- 为接收者发送给Socket的数据包,接收者进程创建一个指向字节数组的DatagramPacket,并调用DatagramSocket对象的receive方法,将DatagramPacket对象引用用作为传递参数。
面向连接数据包Socket API
面向连接数据包Socket API并不经常使用,因为该API提供的连接非常简单,通常不能满足面向连接的通信要求。而流式Socket是面向连接通信中更典型和实用的方法。
流式Socket API
数据包Socket API支持离散数据单元(即数据包)交换,流式Socket API则提供了基于UNIX操作系统的流式IO的数据传输模式。根据定义,流式Socket API仅支持面向对象连接通信。
在Java中,有两个类提供了流式Socket API:SeverSocket和Socket。
- SeverSocket用于接受连接,称之为连接Socket。
- Socket用于数据交换,称之为数据Socket。
客户/服务器范型概述与应用开发方法
客户/服务器范型概念
术语“客户/服务器”在计算机领域中有多种含义。他可以指网络体系结构,其中的网络计算机为实现资源共享而分别承担不同功能的角色。在客户/服务器体系结构中,服务器指专门用于管理打印机或文件等资源的计算机,其他通过服务器访问这些资源的计算机称为客户。在分布式计算中,客户/服务器范型指一种网络应用模型,其中的进程可扮演以下两种角色:服务器进程(也简称服务器)专门用于管理网络服务访问,客户进程(简称客户)访问服务器以获取网络服务。服务器进程运行在网络中的服务器上,管理该主机提供的网络服务;用户利用相应的客户进程访问特定服务。
客户/服务器范型的关键问题
尽管客户/服务器范型的概念是比较简单的,但是在实际应用中仍然有许多关键问题需要解决,如服务会话、读完协议、进程通信、数据表示等。
- 服务会话
在客户/服务器应用环境中,用术语“会话”(session)表示和一个客户之间的交换。服务器管理的服务被多个用户并发访问。每个客户在使用服务器提供的服务时,都单独与服务器建立一个会话。在会话期间,客户与服务器进行对话,直到已获取了所需的服务为止。一旦启动后,服务器进程就无限期地运行,不断循环地接受客户的会话请求。服务器为每一个客户创建一个服务会话。
- 服务协议
为了实现服务,需要有一个协议来定义客户/服务器在服务会话期间必须遵守的规则。这些规则涉及的规范内容包括服务定位的方法、进程间通信的顺序、进程间交换数据的表示及解释。
必须有某种可用的定位机制来确保客户进程能够定位到服务或服务器。一个服务可以通过服务器的进程地址来定位,该地址由分配给服务器进程的主机名和协议端口号组成,这是Internet服务所使用的定位方案。每种Internet服务都被分配了一个特定的端口号。例如,大家熟悉的一些服务如FTP、HTTP或Telnet都被分配了默认的端口号,每台Internet主机都为这类服务保留了这些默认端口号。例如,FTP服务分配了两个端口号,即TCP端口号20和21。HTTP分配的TCP端口号是80。
- 进程间通信
在客户/服务器范型中,进程之间的交互遵循请求-应答的模式。客户在发出的每一个请求后都必须先等待服务器的应答,然后才能进一步继续处理。Daytime(RFC867)是一种简单的网络服务,客户进程仅从服务器进程获取时间戳,该服务可以用自然语言描述如下:
客户:你好,我是<客户地址>。我可以想你要一个时间戳吗?
服务器:给你时间戳。
类似地,WWW会话中的对话按照如下方式进行:
客户:你好,我是<客户地址>。
服务器:你好,我是Web服务器,采用的会话协议是HTTP1.0.
客户:好的。请将你的文档树根目录下的index.html页面传给我。
服务器:好的,这是页面里的内容。
每个会话的对话都遵守该服务协议预先定义的交互模式。任何实现该服务的客户或服务器程序都要遵循该协议规范,包括应该如何进行每个会话对话。除此之外,该规范还定义了:
- 客户和服务器之间的进程通信顺序。
- 每个请求和应答的语法和语义。
- 双方在接收到特定请求或应答后应采取的动作。
- 数据表示
每个请求和应答的语法和语义是协议规范的其中一部分内容。选择使用哪一种数据表示,取决于协议的特性及其需要。使用文本模式表示是一种较为合理的选择,易于被他人阅读。而我们熟知的大部分Internet协议都是基于客户/服务器范型、请求-应答和文本数据表示的。