明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Java 在Client/Server 網(wǎng)絡(luò)中的應(yīng)用 (轉(zhuǎn))

[摘要]Java 在Client/Server 網(wǎng)絡(luò)中的應(yīng)用 (作者: 2000年08月09日 10:19)  隨著Java語(yǔ)言的日益流行,特別是Java與Internet Web的密切結(jié)合,使它在全球取得...
Java 在Client/Server 網(wǎng)絡(luò)中的應(yīng)用
(作者: 2000年08月09日 10:19)

  隨著Java語(yǔ)言的日益流行,特別是Java與Internet Web的密切結(jié)合,使它在全球取得了巨大的成功。Java語(yǔ)言以其獨(dú)立于平臺(tái)、面向?qū)ο蟆⒎植际、多線索及完善的安全機(jī)制等特色,成為現(xiàn)代信息系統(tǒng)建設(shè)中的良好的開(kāi)發(fā)平臺(tái)和運(yùn)行環(huán)境。



一、Java網(wǎng)絡(luò)應(yīng)用模型

  和Internet上的許多環(huán)境一樣,完整的Java應(yīng)用環(huán)境實(shí)際上也是一個(gè)客戶機(jī)/服務(wù)器環(huán)境,更確切地說(shuō)是瀏覽器/服務(wù)器模型(即Browser/Server模型,簡(jiǎn)稱Web模型)。但與傳統(tǒng)的客戶機(jī)/服務(wù)器(C/S) 的二層結(jié)構(gòu)不同,應(yīng)用Java的Web模型是由三層結(jié)構(gòu)組成的。傳統(tǒng)的C/S結(jié)構(gòu)通過(guò)消息傳遞機(jī)制,由客戶端發(fā)出請(qǐng)求給服務(wù)器,服務(wù)器進(jìn)行相應(yīng)處理后經(jīng)傳遞機(jī)制送回客戶端。而在Web模型中,服務(wù)器一端被分解成兩部分:一部分是應(yīng)用服務(wù)器(Web 服務(wù)器),另一部分是數(shù)據(jù)庫(kù)服務(wù)器。

  針對(duì)分布式計(jì)算環(huán)境,Java通過(guò)其網(wǎng)絡(luò)類庫(kù)提供了良好的支持。對(duì)數(shù)據(jù)分布,Java提供了一個(gè)URL(Uniform Resource Locator) 對(duì)象, 利用此對(duì)象可打開(kāi)并訪問(wèn)網(wǎng)絡(luò)上的對(duì)象,其訪問(wèn)方式與訪問(wèn)本地文件系統(tǒng)幾乎完全相同。對(duì)操作分布,Java的客戶機(jī)/ 服務(wù)器模式可以把運(yùn)算從服務(wù)器分散到客戶一端(服務(wù)器負(fù)責(zé)提供查詢結(jié)果,客戶機(jī)負(fù)責(zé)組織結(jié)果的顯示),從而提高整個(gè)系統(tǒng)的執(zhí)行效率,增加動(dòng)態(tài)可擴(kuò)充性。Java網(wǎng)絡(luò)類庫(kù)是Java 語(yǔ)言為適應(yīng)Internet 環(huán)境而進(jìn)行的擴(kuò)展。另外,為適應(yīng)Internet的不斷發(fā)展,Java還提供了動(dòng)態(tài)擴(kuò)充協(xié)議,以不斷擴(kuò)充Java網(wǎng)絡(luò)類庫(kù)。

  Java的網(wǎng)絡(luò)類庫(kù)支持多種Internet協(xié)議,包括Telnet, FTP 和HTTP (WWW),與此相對(duì)應(yīng)的Java網(wǎng)絡(luò)類庫(kù)的子類庫(kù)為:

Java.net

Java.net.ftp

Java.net.www.content

Java.net.www.html

Java.net.www.http

  這些子類庫(kù)各自容納了可用于處理Internet協(xié)議的類和方法。其中,java.net用于處理一些基本的網(wǎng)絡(luò)功能,包括遠(yuǎn)程登錄(Telnet);java.net.ftp用于處理ftp協(xié)議;java.net.www.content用于處理WWW 頁(yè)面內(nèi)容;java.net.www.html 和java.net.www.http 則分別提供了對(duì)HTML 語(yǔ)言和HTTP 協(xié)議的支持。



二、客戶機(jī)/服務(wù)器環(huán)境下的Java應(yīng)用程序

客戶機(jī)/服務(wù)器在分布處理過(guò)程中,使用基于連接的網(wǎng)絡(luò)通信模式。該通信模式首先在客戶機(jī)和服務(wù)器之間定義一套通信協(xié)議,并創(chuàng)建一Socket類,利用這個(gè)類建立一條可靠的鏈接;然后,客戶機(jī)/服務(wù)器再在這條鏈接上可靠地傳輸數(shù)據(jù)。客戶機(jī)發(fā)出請(qǐng)求,服務(wù)器監(jiān)聽(tīng)來(lái)自客戶機(jī)的請(qǐng)求,并為客戶機(jī)提供響應(yīng)服務(wù)。這就是典型的"請(qǐng)求-- 應(yīng)答" 模式。下面是客戶機(jī)/服務(wù)器的一個(gè)典型運(yùn)作過(guò)程:

1、服務(wù)器監(jiān)聽(tīng)相應(yīng)端口的輸入;

2、客戶機(jī)發(fā)出一個(gè)請(qǐng)求;

3、服務(wù)器接收到此請(qǐng)求;

4、服務(wù)器處理這個(gè)請(qǐng)求,并把結(jié)果返回給客戶機(jī);

5、重復(fù)上述過(guò)程,直至完成一次會(huì)話過(guò)程。

  按照以上過(guò)程,我們使用Java語(yǔ)言編寫一個(gè)分別針對(duì)服務(wù)器和客戶機(jī)的應(yīng)用程序(Application)。該程序在服務(wù)器上時(shí),程序負(fù)責(zé)監(jiān)聽(tīng)客戶機(jī)請(qǐng)求,為每個(gè)客戶機(jī)請(qǐng)求建立Socket 連接,從而為客戶機(jī)提供服務(wù)。本程序提供的服務(wù)為:讀取來(lái)自客戶機(jī)的一行文本,反轉(zhuǎn)該文本,并把它發(fā)回給客戶機(jī)。

  通過(guò)該程序?qū)嵗覀兛吹,使用Java語(yǔ)言設(shè)計(jì)C/S程序時(shí)需要注意以下幾點(diǎn):

(1)、 服務(wù)器應(yīng)使用ServerSocket 類來(lái)處理客戶機(jī)的連接請(qǐng)求。當(dāng)客戶機(jī)連接到服務(wù)器所監(jiān)聽(tīng)的端口時(shí),ServerSocket將分配一新的Socket 對(duì)象。這個(gè)新的Socket 對(duì)象將連接到一些新端口,負(fù)責(zé)處理與之相對(duì)應(yīng)客戶機(jī)的通信。然后,服務(wù)器繼續(xù)監(jiān)聽(tīng)ServerSocket,處理新的客戶機(jī)連接。

  Socket 和ServerSocket 是Java網(wǎng)絡(luò)類庫(kù)提供的兩個(gè)類。

(2)、服務(wù)器使用了多線程機(jī)制。Server對(duì)象本身就是一個(gè)線程,它的run()方法是一個(gè)無(wú)限循環(huán),用以監(jiān)聽(tīng)來(lái)自客戶機(jī)的連接。每當(dāng)有一個(gè)新的客戶機(jī)連接時(shí),ServerSocket就會(huì)創(chuàng)建一個(gè)新的Socket類實(shí)例,同時(shí)服務(wù)器也將創(chuàng)建一新線程,即一個(gè)Connection 對(duì)象,以處理基于Socket 的通信。與客戶機(jī)的所有通信均由這個(gè)Connection 對(duì)象處理。Connection的構(gòu)造函數(shù)將初始化基于Socket 對(duì)象的通信流,并啟動(dòng)線程的運(yùn)行。與客戶機(jī) 的通信以及服務(wù)的提供,均由Connection對(duì)象處理。

(3)、客戶機(jī)首先創(chuàng)建一Socket對(duì)象,用以與服務(wù)器通信。之后需創(chuàng)建兩個(gè)對(duì)象:DataInputStream 和PrintStream,前者用以從Socket 的InputStream 輸入流中讀取數(shù)據(jù),后者則用于往Socket的OutputStream 中寫數(shù)據(jù)。最后,客戶機(jī)程序從標(biāo)準(zhǔn)輸入(如:控制臺(tái))中讀取數(shù)據(jù),并把這些數(shù)據(jù)寫到服務(wù)器,在從服務(wù)器讀取應(yīng)答消息,然后把這些應(yīng)答消息寫到準(zhǔn)輸出。

  以下分別為服務(wù)器和客戶機(jī)端的源程序清單。本程序在NT 4.0 網(wǎng)絡(luò)環(huán)境(TCP/IP)下使用JDK1.1 調(diào)試通過(guò)。



三、編寫服務(wù)器類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;

// 定義出錯(cuò)例程:如果出現(xiàn)異常錯(cuò)誤,退出程序。

Public static void fail(Exception e, String msg)

{

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

    System.exit(1);

}

// 定義并啟動(dòng)服務(wù)器的Socket 例程,監(jiān)聽(tīng)客戶機(jī)的連接請(qǐng)求。

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();

}

/* 下面為服務(wù)器監(jiān)聽(tīng)線程的主程序。該線程一直循環(huán)執(zhí)行,監(jiān)聽(tīng)并接受客戶機(jī)發(fā)出的連接

請(qǐng)求。對(duì)每一個(gè)連接,均產(chǎn)生一個(gè)連接對(duì)象與之對(duì)應(yīng),通過(guò)Socket 通道進(jìn)行通信。*/

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")

}

// 啟動(dòng)服務(wù)器主程序

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 類,它是用來(lái)處理與客戶機(jī)的所有通信的線程。

class Connection extends Thread

{

protected Socket client;

    protected DataInputStream in;

        protected PrintStream out;

// 初始化通信流并啟動(dòng)線程

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

// 服務(wù)例程:讀出一行文本;反轉(zhuǎn)文本;返回文本。

public void run()

{

        String line;

    StringBuffer revline;

int len;

    try

{

        for(;;)

{

            // Read a line

                line = in.readline();

                    if(line == null) break;

        // Reverse the line

                len = line.length();

                revline = new StringBuffer(len);

        for(int i = len-1; i >=0; i--)

        revline.insert(len-1-I;line.charAt(i));

           // Write out the reverse line

        out.println(revline);

            }

catch(IOException e);

finally try client.close();

catch(IOException e2);

}

// End of run method

}

// End of Connection class

3、編寫客戶機(jī)類Java 程序

// Client.java

import java.io.*;

import java.net.*;

public class Client extends

{

    public static final int Default_Port = 6543;

// 定義出錯(cuò)例程

    public static final void usage()

    {

    System.out.println("Usage: Java Client []");

        System.exit(0);

}

    public static void main(String args[])

{

    int port = Default_Port;

Socket s = null;

// 解析端口參數(shù)

if ((args.length != 1)&&(args.length != 2 )) usage();

if (args.length == 1)

    port = Default_Port;

else

{

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

    catch(NumberFormaatException e) usage();

}

try{

    // 產(chǎn)生一個(gè)Socket ,通過(guò)指定的端口與主機(jī)通信。

    s = new Socket(args[0], port);

// 產(chǎn)生用于發(fā)出和接收的文本字符流

DataInputStream sin = new DataInputStream(s.getInputStream());

PrintStream sout = new DataInputStream(s.getInputStream());

// 從控制臺(tái)讀入字符流

DataInputStream in = new DataInputStream(System.in);

    // 返回連接的地址和端口

System.out.println("Connected to"+s.getInetAddress()+":"+ s.getPort());

    String line;

    For(;;)

    {

        // 顯示提示符

        System.out.print(" >");

        System.out.flush();

        // 讀入控制臺(tái)輸入的一行字符

        line = in.readline();

        if (line == null) break;

        // 將接收的文本行送至服務(wù)器

        sout.println(line);

        // 從服務(wù)器接收一行字符

        line = sin.readline();

        // Check if connection is closed(i.e. for EOF)

        if(line == null)

        {

            System.out.println("Connection closed by server.");

            Break;

}

    // 在控制臺(tái)上顯示接收的字符

    System.out.println(line);

}

// End of for loop

}

/ End of try

catch(IOException e ) System.err.println(e);

// Always be sure to close the socket

finally

{

    try if(s != null) s.close();

    catch(IOException e2);

}

}                       // End of main

}               // End of Client

運(yùn)行該客戶機(jī)程序時(shí),必須以服務(wù)器主機(jī)名作為第一個(gè)參數(shù),服務(wù)器端口號(hào)為第二個(gè)參數(shù),

其中服務(wù)器端口號(hào)可缺省。