程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java在Client/Server網絡中的應用

Java在Client/Server網絡中的應用

編輯:關於JAVA

隨著Java語言的日益流行,特別是Java與Internet Web的密切結合,使它在 全球取得了巨大的成功。Java語言以其獨立於平台、面向對象、分布式、多線索 及完善的安全機制等特色,成為現代信息系統建設中的良好的開發平台和運行環 境。

一、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
   // 服務例程:讀出一行文本;反轉文本;返回文本。
   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、編寫客戶機類Java 程序
   // Client.java
   import java.io.*;
   import java.net.*;
   public class Client extends
   {
   public static final int Default_Port = 6543;
   // 定義出錯例程
   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;
   // 解析端口參數
   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{
   // 產生一個Socket ,通過指定的端口與主機通信。
   s = new Socket(args[0], port);
   // 產生用於發出和接收的文本字符流
   DataInputStream sin = new DataInputStream(s.getInputStream ());
   PrintStream sout = new DataInputStream(s.getInputStream());
   // 從控制台讀入字符流
   DataInputStream in = new DataInputStream(System.in);
   // 返回連接的地址和端口
   ystem.out.println("Connected to"+s.getInetAddress()+":"+ s.getPort());
   String line;
   For(;;)
   {
   // 顯示提示符
   System.out.print(" >");
   System.out.flush();
   // 讀入控制台輸入的一行字符
   line = in.readline();
   if (line == null) break;
   // 將接收的文本行送至服務器
   sout.println(line);
   // 從服務器接收一行字符
   line = sin.readline();
   // Check if connection is closed(i.e. for EOF)
   if(line == null)
   {
   System.out.println("Connection closed by server.");
   Break;
   }
   // 在控制台上顯示接收的字符
   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

運行該客戶機程序時,必須以服務器主機名作為第一個參數,服務器端口號 為第二個參數,其中服務器端口號可缺省。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved