Java 在Client/Server 中应用


  一、Java网络 利用模型

和Internet上的许多环境一样, 完全的Java 利用环境实际上也是一个客户机/服务器环境,更确切地说是阅读器/服务器模型(即Browser/Server模型,简称Web模型) 。但与传统的客户机/服务器(C/S) 的二层 构造不同, 利用Java的Web模型是由三层 构造构成的 。传统的C/S 构造通过 信息传递机制,由客户端发出 申请给服务器,服务器进行相应 解决后经传递机制送回客户端 。而在Web模型中,服务器一端被分解成两 部分:一 部分是 利用服务器(Web 服务器),另一 部分是数据库服务器 。

针对 分布式计算环境,Java通过其网络类库提供了良好的 支撑 。对数据 分布,Java提供了一个URL(Uniform Resource Locator) 对象, 利用此对象可 打开并 拜访网络上的对象,其 拜访 模式与 拜访当地文件系统 几乎 彻底 雷同 。对操作 分布,Java的客户机/ 服务器模式 可以把运算从服务器 疏散到客户一端(服务器负责提供 查问 后果,客户机负责组织 后果的显示),从而 普及整个系统的执行效率,添加动态可扩充性 。Java网络类库是Java 语言为适应Internet 环境而进行的 扩大 。另外,为适应Internet的不停进展,Java还提供了动态扩充 协定,以不停扩充Java网络类库 。

Java的网络类库 支撑多种Internet 协定,包含Telnet, FTP 和HTTP (WWW),与此 绝对应的Java网络类库的子类库为:

Java.net

Java.net.ftp

Java.net.www.content

Java.net.www.html

Java.net.www.http

这些子类库各自 包容了可用于 解决Internet 协定的类和 步骤 。其中,java.net用于 解决一些 根本的网络 性能,包含远程登录(Telnet);java.net.ftp用于 解决ftp 协定;java.net.www.content用于 解决WWW 页面内容;java.net.www.html 和java.net.www.http 则分别提供了对HTML 语言和HTTP 协定的 支撑 。

  二、客户机/服务器环境下的Java 利用程序

客户机/服务器在 分布 解决过程中, 使用基于衔接的网络通讯模式 。该通讯模式首先在客户机和服务器中间定义一套通讯 协定,并 缔造一Socket类,利用这个类 构建一条牢靠的链接; 而后,客户机/服务器再在这条链接上牢靠地传输数据 。客户机发出 申请,服务器监听来自客户机的 申请,并为客户机提供响应服务 。这便是典型的" 申请-- 应答" 模式 。下面是客户机/服务器的一个典型运作过程:

1、服务器监听相应端口的输入;

2、客户机发出一个 申请;

3、服务器 接纳到此 申请;

4、服务器 解决这个 申请,并把 后果返回给客户机;

5、 反复上述过程,直至 实现一次会话过程 。

依照以上过程,我们 使用Java语言编写一个分别针对服务器和客户机的 利用程序(Application) 。该程序在服务器上时,程序负责监听客户机 申请,为每个客户机 申请 构建Socket 衔接,从而为客户机提供服务 。本程序提供的服务为:读取来自客户机的一行文本,反转该文本,并把它发回给客户机 。

  通过该程序实例我们看到, 使用Java语言设计C/S程序时需求 留神以下几点:

(1)、 服务器应 使用ServerSocket 类来 解决客户机的衔接 申请 。当客户机衔接到服务器所监听的端口时,ServerSocket将 调配一新的Socket 对象 。这个新的Socket 对象将衔接到一些新端口,负责 解决与之 绝对应客户机的通讯 。 而后,服务器 接续监听ServerSocket, 解决新的客户机衔接 。

Socket 和ServerSocket 是Java网络类库提供的两个类 。

(2)、服务器 使用了多线程机制 。Server对象 本身便是一个线程,它的run() 步骤是一个无限循环,用以监听来自客户机的衔接 。每当有一个新的客户机衔接时,ServerSocket就会 缔造一个新的Socket类实例,同时服务器也将 缔造一新线程,即一个Connection 对象,以 解决基于Socket 的通讯 。与客户机的全部通讯均由这个Connection 对象 解决 。Connection的 构造函数将初始化基于Socket 对象的通讯流,并启动线程的运行 。与客户机 的通讯以及服务的提供,均由Connection对象 解决 。

(3)、客户机首先 缔造一Socket对象,用以与服务器通讯 。之后需 缔造两个对象:DataInputStream 和PrintStream,前者用以从Socket 的InputStream 输入流中读取数据,后者则用于往Socket的OutputStream 中写数据 。最终,客户机程序从 标准输入(如:操纵台)中读取数据,并把这些数据写到服务器,在从服务器读取应答 信息, 而后把这些应答 信息写到准输出 。

以下分别为服务器和客户机端的源程序清单 。本程序在NT 4.0 网络环境(TCP/IP)下 使用JDK1.1 调试通过 。

三、编写服务器类Java程序

// Server.java

import java.io.*;

import java.net.*;

public class Server extends Thread

{

public final static int Default_Port=6543;

protectd int port;

protectd ServerSockt listen_socket;

// 定义出错例程:假如浮现 异样 舛误,退出程序 。

Public static void fail(Exception e, String msg)

{

System.err.println(msg + ": " + e);

System.exit(1);

}

// 定义并启动服务器的Socket 例程,监听客户机的衔接 申请 。

public Server(int port)

{

if(port == 0) port = Default_Port;

this.port = port;

try

{

listen_socket = new ServerSocket(port);

}

catch(IOException e) fail(e, "Exception creating server socket");

System.out.println("Server: listening on port" + port);

This.start();

}

/* 下面为服务器监听线程的主程序 。该线程向来循环执行,监听并 承受客户机发出的衔接

申请 。对每一个衔接,均产生一个衔接对象与之对应,通过Socket 通道进行通讯 。*/

public void run()

{

try

{

while(true)

{

Socket client_socket = listen_socket.accept();

Connection c = new Connection(client_socket);

}

}

catch(IOException e) fail(e,"Exception while listening for connections")

}

// 启动服务器主程序

public static void main(String args[])

{

int port = 0;

if (args.length == 1)

{

try port = Integer.parseInt(args[0]);

catch(NumberFormatException e) port = 0;

}

new Server(port);

// End of the main

} // End of Server class

//以下定义了Connection 类,它是用来 解决与客户机的全部通讯的线程 。

class Connection extends Thread

{

protected Socket client;

protected DataInputStream in;

protected PrintStream out;

// 初始化通讯流并启动线程

public Connection(Socket client_socket)

{

client = client_socket;

try

{

in = new DataInputStream(client.getinputStream());

out = new PrintStream(client.getOutputStream());

}

catch(IOException e)

{

try client.close();

catch(IOException e2);

System.err.println("Exception while getting socket streram: " + e);

Return;

}

this.start;

} // End of Connection method

// 服务例程:读出一行文本;反转文本;返回文本 。