OMG,到底在尋找什么..................
          (構(gòu)造一個(gè)完美的J2EE系統(tǒng)所需要的完整知識(shí)體系)
          posts - 198,  comments - 37,  trackbacks - 0
          原貼地址http://blog.csdn.net/clearwater21cn/category/99145.aspx

          QuickServer開(kāi)發(fā)指南(1)- 介紹?

          QuickServer是一個(gè)免費(fèi)的開(kāi)源Java庫(kù),用于快速創(chuàng)建健壯的多線程、多客戶端TCP服務(wù)器應(yīng)用程序。使用QuickServer,用戶可以只集中處理應(yīng)用程序的邏輯/協(xié)議,從而方便的建立功能強(qiáng)大的服務(wù)器應(yīng)用。該程序由Akshathkumar Shetty設(shè)計(jì)和實(shí)現(xiàn)。
          ??? QuickServer安裝目錄下的example中有演示其功能的例子,最新的例子和文檔可以通過(guò)網(wǎng)站 http://www.quickserver.orghttp://quickserver.sourceforge.net獲得。
          ??? 該指南適用于所有想要學(xué)習(xí)和使用QuickServer的人,閱讀該指南應(yīng)具備基本的Java編程知識(shí),基本的網(wǎng)絡(luò)和sockets方面的知識(shí)也會(huì)有所幫助

          1.?為什么需要QuickServer?
          ??? 無(wú)論何種編程語(yǔ)言,socket編程對(duì)程序員來(lái)說(shuō)都不是一件容易的事,創(chuàng)建多線程、多客戶端的服務(wù)器socket更像一場(chǎng)惡夢(mèng)了。在每個(gè)新的軟件中處理多socket連接,我們都要浪費(fèi)大把時(shí)間編寫大量重復(fù)的代碼。QuickServer因而誕生——使用Java創(chuàng)建多線程、多客戶端服務(wù)器應(yīng)用。

          2.?基本構(gòu)造
          QuickServer在應(yīng)用邏輯上為開(kāi)發(fā)者提供了四個(gè)類
          o?ClientCommandHandler
          ??? 處理與客戶端的交互——使用字符串命令
          o?ClientObjectHandler [可選類]
          ??? 處理與客戶端的交互——使用對(duì)象命令
          o?Authenticator [可選類]
          ??? 客戶端驗(yàn)證
          o?ClientData [可選類]
          ??? 客戶端數(shù)據(jù)載體(支持類)
          下面的圖表顯示了QuickServer庫(kù)的基本構(gòu)造。QuickServer模塊上七個(gè)輻條表示七個(gè)方法:
          o?java.lang.String info()
          o?int getServiceState()
          o?boolean initService(java.lang.Object[] config)
          o?boolean startService()
          o?boolean resumeService()
          o?boolean suspendService()
          o?boolean stopService()


          ??? 與QuickServer模塊相連接的四個(gè)組件中只有ClientCommandHandler是必須的。
          ??? QuickServerConfig對(duì)象由initService()方法構(gòu)建。它實(shí)現(xiàn)了QuickServer,在讀取XML配置后,QuickServerConfig用于QuickServer配置。
          ??? ClientHandler線程對(duì)象用于客戶端緩沖池??蛇x的ClientData類與ClientHandler類關(guān)聯(lián),ClientHandler對(duì)象容器參考ClientCommandHandler,ClientObjectHandler(可選),Authenticator(可選)對(duì)象包含在QuickServer主函數(shù)中。
          ??? 注意:上圖中并未顯示QSAdminServer,它是圖中QuickServer的組成部分。

          3.?主要特點(diǎn)
          o?創(chuàng)建多線程、多客戶端TCP服務(wù)器應(yīng)用程序
          o?支持安全服務(wù)的創(chuàng)建:SSL, TLS
          o?清楚的分離服務(wù)、協(xié)議、驗(yàn)證邏輯
          o?GUI圖形界面遠(yuǎn)程管理支持
          o?Command Shell對(duì)服務(wù)器的本地管理
          o?無(wú)須斷開(kāi)客戶端連接的重啟或延遲服務(wù)
          o?為線程的再利用和大多數(shù)的使用對(duì)象建立緩沖池
          o?完全的日志支持(Java構(gòu)建)
          o?支持發(fā)送和接收字符串、字節(jié)、二進(jìn)制、序列化Java對(duì)象
          o?在同樣的xml中支持能夠存貯指定應(yīng)用數(shù)據(jù)的XML配置
          o?支持通過(guò)IP地址限制服務(wù)
          o?支持基于XML的JDBC映射
          o?支持服務(wù)配置模式
          o?支持從xml加載/重新加載用于jar包
          o?在QuickServer中添加處理hooks
          o?指定允許的最大客戶端連接數(shù)
          o?在通常的TCP連接上支持談判安全連接
          o?支持鑒別和查詢客戶端
          o?附帶典型例子——FTPServer, CmdServer,EchoWebServer, ChatServer

          4.?1.4版的新功能
          o?為QuickServer添加安全模式:SSL, TLS
          o?添加SecureManagerLoader管理安全模式
          o?在通常的TCP連接上添加談判安全連接
          o?添加初始化服務(wù)hooks
          o?為通信添加二進(jìn)制模式
          o?為QsAdminServer通信添加QSAdminAPI
          o?為QuickServer 添加findAllClientByKey
          o?添加ConnectionLostException類
          o?改進(jìn)ClientHandler、安全配置
          o?新例子——XmlAdder:一個(gè)簡(jiǎn)單的xml服務(wù),可添加兩個(gè)整數(shù)
          o?新例子——PipeServer:一個(gè)簡(jiǎn)單的重定向服務(wù)

          QuickServer開(kāi)發(fā)指南(2)- 安裝

          1. 運(yùn)行環(huán)境
          QuickServer 1.2以上的版本需要(其實(shí)在偶看來(lái)一個(gè)1.4版以上JDK足矣):
          ? 推薦1.4版以上Java虛擬機(jī),最低1.3版(未經(jīng)測(cè)試).
          ? Java Logging API(下列之一)
          o java.util.logging包 [JDK 1.4版自帶]
          o Lumberjack庫(kù) [http://javalogging.sourceforge.net/]
          ? XML 解析器 (下列之一)
          o SAX (面向XML 2.0的API) [JDK 1.4版自帶]
          o JAXP (面向XML解析的Java API) 1.1 [JDK 1.4版自帶]
          o Xerces [http://xml.apache.org/xerces2-j]
          o Crimson [http://xml.apache.org/crimson]
          ? Jakarta公共組件{Digester, Pool}
          o 這些產(chǎn)品包含在Apache開(kāi)發(fā)的軟件中(http://www.apache.org/)。Jar包都在以下的庫(kù)中:BeanUtils, Collections, Logging. [http://jakarta.apache.org/commons/components.html]. Apache軟件許可證在文件“apache_license.txt”中。

          2. 安裝
          ??? 目前最新的1.4.1版QuickServer可在http://www.quickserver.org/download.html下載。安裝QuickServer,假設(shè)安裝路徑為$INSTALL_PATH。
          ??? 在CLASSPATH中添加"$INSTALL_PATH\dist\QuickServer.jar",在PATH中添加"$INSTALL_PATH\bin"。
          ??? 另外測(cè)試socket的通訊軟件推薦SockTest,在http://www.ddost.com/soft/sockettest 可下載到最新版本。Windows自帶的telnet也可以進(jìn)行測(cè)試。

          QuickServer開(kāi)發(fā)指南(3)- 構(gòu)建EchoServer?

          學(xué)習(xí)怎樣使用QuickServer庫(kù)的一個(gè)好的方法是學(xué)習(xí)它提供的例子。在QuickServer安裝路徑下的examples文件夾里有許多典型的例子。
          ??? 下面的章節(jié)里我們模仿其中的一個(gè)例子EchoServer來(lái)構(gòu)建一個(gè)服務(wù)器。EchoServer是一個(gè)簡(jiǎn)單的TCP服務(wù)器,主要功能是將用戶發(fā)送的字符串加上前綴"Echo :"后返回。雖然這個(gè)例子可用性不強(qiáng),但它是一個(gè)對(duì)QuickServer所有特點(diǎn)的一個(gè)很好的示范。我們從構(gòu)建一個(gè)最基本的服務(wù)器開(kāi)始,以后慢慢給它添加新的功能。

          1.?代碼
          ??? 首先實(shí)現(xiàn)EchoServer最基本的功能:將用戶發(fā)送的字符串加上前綴"Echo :"后返回。
          ??? 在本地創(chuàng)建一個(gè)文件夾存放需要的代碼,如在c:\projects\中建立echoserver文件夾,然后創(chuàng)建一個(gè)類EchoServer.java:

          01 package echoserver;

          02

          03 import org.quickserver.net.*;

          04 import org.quickserver.net.server.*;

          05

          06 import java.io.*;

          07

          08 public class EchoServer {

          09 public static void main(String s[]) {

          10 QuickServer myServer =

          11 new QuickServer("echoserver.EchoCommandHandler");

          12 myServer.setPort(4123);

          13 myServer.setName("EchoServer v 1.0");

          14 try {

          15 myServer.startServer();

          16 } catch(AppException e){

          17 System.err.println("Error in server : "+e);

          18 }

          19 }

          20 }


          ??? 在第10行和第11行定義了一個(gè)QuickServer對(duì)象myServer,通過(guò)一個(gè)String對(duì)象"echoserver.EchoCommandHandler"聲明了要加載的類,這個(gè)類面向所有客戶端做命令處理器,實(shí)現(xiàn)了org.quickserver.net.server.ClientCommandHandler接口,我們即將創(chuàng)建。
          ??? 第12行設(shè)置了一個(gè)服務(wù)器端口用來(lái)做監(jiān)聽(tīng),然后設(shè)置整個(gè)應(yīng)用的名字(第13行)。最后啟動(dòng)服務(wù)(第15行)。

          ??? 接下來(lái)為EchoServer創(chuàng)建一個(gè)實(shí)現(xiàn)org.quickserver.net.server.ClientCommandHandler接口的類EchoCommandHandler.java,用來(lái)處理服務(wù)器發(fā)送的命令。

          01 // EchoCommandHandler.java

          02 package echoserver;

          03

          04 import java.net.*;

          05 import java.io.*;

          06 import org.quickserver.net.server.ClientCommandHandler;

          07 import org.quickserver.net.server.ClientHandler;

          08

          09 public class EchoCommandHandler implements ClientCommandHandler {

          10

          11 public void gotConnected(ClientHandler handler)

          12 throws SocketTimeoutException, IOException {

          13 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

          14 handler.sendClientMsg("| Welcome to EchoServer v 1.3 |");

          15 handler.sendClientMsg("| Send 'Quit' to exit |");

          16 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

          17 }

          18 public void lostConnection(ClientHandler handler)

          19 throws IOException {

          20 handler.sendSystemMsg("Connection lost : " +

          21 handler.getSocket().getInetAddress());

          22 }

          23 public void closingConnection(ClientHandler handler)

          24 throws IOException {

          25 handler.sendSystemMsg("Closing connection : " +

          26 handler.getSocket().getInetAddress());

          27 }

          28

          29 public void handleCommand(ClientHandler handler, String command)

          30 throws SocketTimeoutException, IOException {

          31 if(command.equals("Quit")) {

          32 handler.sendClientMsg("Bye ;-)");

          33 handler.closeConnection();

          34 } else {

          35 handler.sendClientMsg("Echo : "+command);

          36 }

          37 }

          38 }


          ??? 根據(jù)QuickServer的要求,這個(gè)類必須實(shí)現(xiàn)ClientCommandHandler接口。
          ??? 當(dāng)客戶端建立一個(gè)連接(11行),gotConnected()方法被調(diào)用。在這個(gè)方法里面,我們給客戶端發(fā)送歡迎文本(13-16行),這些文本使用通過(guò)ClientHandler的sendClientMsg()方法發(fā)送給客戶端。我們也會(huì)使用ClientHandler的sendSystemMessage()方法顯示客戶端連接的InetAddress(20-21,25-26行)。
          ??? handlerCommand()方法是ClientCommandHandler接口的核心方法,因?yàn)榉?wù)器接收客戶端發(fā)送的任何命令時(shí)都要調(diào)用該方法。在我們對(duì)這個(gè)方法的實(shí)現(xiàn)中,我們會(huì)檢查命令是否為"Quit"(31行),如果是,我們將發(fā)送一些提示文本表示服務(wù)器即將關(guān)閉連接,然后關(guān)閉連接(33行)。否則,將命令加上前綴"Echo :"返回給用戶。

          2.?運(yùn)行和測(cè)試
          o?運(yùn)行命令提示符程序(cmd.exe)
          o?進(jìn)入代碼所在文件夾根目錄,如c:\projects
          o?編譯代碼? javac echoserver\*.java
          o?若無(wú)編譯錯(cuò)誤,運(yùn)行服務(wù)器:
          ??? set classpath=%classpath%;d:\QuickServer\dist\QuickServer.jar;.\(類所在文件夾)
          ??? java echoserver.EchoServer
          o?您將會(huì)看到如下信息:

          o?測(cè)試我們的服務(wù)器是否可以正常工作。再運(yùn)行一個(gè)cmd程序,進(jìn)入SocketTest.jar所在目錄,鍵入java -jar sockettest.jar命令,彈出一個(gè)窗口。在IP Address中輸入"127.0.0.1",在Port里輸入"4123",點(diǎn)擊"Connect"按鈕,將看到窗口中顯示如下圖的信息。


          ??? 若使用telnet,可鍵入命令:open localhost 4123
          ??? 在Message中輸入一些字符串,點(diǎn)擊"Send"按鈕,瀏覽器將會(huì)返回一個(gè)加了前綴"Echo :"的字符串。發(fā)送"Quit",服務(wù)器斷開(kāi)連接。

          QuickServer開(kāi)發(fā)指南(4)- 添加認(rèn)證

          現(xiàn)在我們給剛剛創(chuàng)建的服務(wù)器添加認(rèn)證功能。
          ??? 查看org.quickserver.net.server.QuickServer的文檔(docs文件夾下)你可以注意到里面有一個(gè)方法
          ??? public void setAuthenticator(java.lang.String authenticator)
          ??? 閱讀文檔可知此方法中的authenticator字符串是實(shí)現(xiàn)org.quickserver.net.server.Authenticator接口的方法的全名。
          ??? Authenticator接口有兩個(gè)實(shí)現(xiàn):
          ??? org.quickserver.net.server.QuickAuthenticator:這個(gè)類用來(lái)驗(yàn)證連接QuickServer的客戶端。它只用一個(gè)實(shí)例處理所有的QuickServer驗(yàn)證。(推薦)
          ??? org.quickserver.net.server.ServerAuthenticator:這個(gè)類同樣用來(lái)驗(yàn)證連接QuickServer的客戶端,但對(duì)每一個(gè)驗(yàn)證的處理都會(huì)創(chuàng)建一個(gè)實(shí)例。
          ??? 接下來(lái)給EchoServer加驗(yàn)證功能。簡(jiǎn)單點(diǎn),客戶端輸入的用戶名和密碼一致就算驗(yàn)證通過(guò)。
          ??? 首先,在同樣的文件夾里創(chuàng)建一個(gè)驗(yàn)證類:EchoServerQuickAuthenticator

          01 package echoserver;

          02

          03 import org.quickserver.net.server.*;

          04 import java.io.*;

          05

          06 public class EchoServerQuickAuthenticator extends QuickAuthenticator {

          07

          08 public boolean askAuthorisation(ClientHandler clientHandler)

          09 throws IOException {

          10 String username = askStringInput(clientHandler, "User Name :");

          11 String password = askStringInput(clientHandler, "Password :");

          12

          13 if(username==null || password ==null)

          14 return false;

          15

          16 if(username.equals(password)) {

          17 sendString(clientHandler, "Auth OK");

          18 return true;

          19 } else {

          20 sendString(clientHandler, "Auth Failed");

          21 return false;

          22 }

          23 }

          24 }

          ??? 這個(gè)類擴(kuò)展了org.quickserver.net.server.QuickAuthenticator(第6行),在askAuthorisation()方法中(8行),通過(guò)askStringInput()方法要求客戶端輸入用戶名和密碼,并讀入客戶端輸入的信息(10-11行)。這個(gè)方法繼承自QuickAuthenticator。如果用戶名與密碼相等,發(fā)送正確信息并返回"true"(16-18行),否則發(fā)送錯(cuò)誤信息并返回"false"(20-21行)。

          ??? 接下來(lái)我們要告訴QuickServer使用我們新創(chuàng)建的驗(yàn)證類來(lái)做驗(yàn)證器。修改前一章創(chuàng)建的EchoServer.java文件,代碼如下(粗體為修改的代碼):

          01 package echoserver;

          02

          03 import com.ddost.net.*;

          04 import com.ddost.net.server.*;

          05

          06 import java.io.*;

          07

          08 public class EchoServer {

          09

          10 public static void main(String s[]) {

          11

          12 QuickServer myServer =

          13 new QuickServer("echoserver.EchoCommandHandler");

          14myServer.setAuthenticator(

          15"echoserver.EchoServerQuickAuthenticator");

          16 myServer.setPort(4123);

          17 myServer.setName("EchoServer v 1.0");

          18try {

          19 myServer.startServer();

          20 } catch(AppException e){

          21 System.err.println("Error in server : "+e);

          22 }

          23 }

          24 }


          ??? OK,將修改好的文件編譯,按照前一章講述的方法運(yùn)行程序。這次當(dāng)我們點(diǎn)擊"Connect"時(shí),瀏覽器會(huì)要求我們輸入用戶名和密碼。如果輸入的用戶名和密碼一致就可以登錄。如果輸入錯(cuò)誤五次以上,瀏覽器會(huì)提示"-ERR Max Auth Try Reached"并自動(dòng)斷開(kāi)連接。這個(gè)次數(shù)和提示信息可以通過(guò)QuickServer類的setMaxAuthTry() 和 setMaxAuthTryMsg()修改。


          ??? 有時(shí)在驗(yàn)證過(guò)程中我們可能需要中途退出而不是等待驗(yàn)證結(jié)束,這時(shí)輸入"Quit"是不起作用的。我們可以這樣修改代碼,有兩個(gè)方法:
          ??? 一是從EchoServerQuickAuthenticator類中的askAuthorisation()方法拋出一個(gè)org.quickserver.net.AppException異常,代碼如下:
          ??? String username = askStringInput(clientHandler, "User Name :");
          ??? if (username != null &&
          ??????? username.equalsIgnoreCase("QUIT")) {
          ????? sendString(clientHandler, "Logged out.");
          ????? throw new AppException("Quit");
          }
          ??? 或者參考ClientHandler,關(guān)閉連接,代碼如下:
          ??? String username = askStringInput(clientHandler, "User Name :");
          ??? if (username != null &&
          ??????? username.equalsIgnoreCase("QUIT")) {
          ????? sendString(clientHandler, "Logged out.");
          ????? clientHandler.closeConnection();
          ????? return false;
          }
          ??? ClientHandler對(duì)象能夠提供很多客戶端連接的有用信息,如IP地址。更多信息請(qǐng)參考API文檔。

          注意:
          ??? o 不要在驗(yàn)證器類中存貯任何客戶端相關(guān)信息,如果需要,必須存放在ClientData類中--下一章將講解該部分內(nèi)容。
          ??? o 必須確認(rèn)askAuthorisation()方法是線程安全的。

          QuickServer開(kāi)發(fā)指南(5)- 客戶數(shù)據(jù)

          既然不能在ClientCommandHandler和ServerAuthenticator類中保存客戶數(shù)據(jù),我們使用ClientData類的handleCommand()或askAuthorisation()方法來(lái)存儲(chǔ)所有的客戶端信息。
          ??? 示范一下這個(gè)特點(diǎn)有什么用。還是以EchoServer為例,當(dāng)用戶發(fā)送"Hello"時(shí),我們給他一個(gè)問(wèn)候。如果用戶再發(fā)送"Hello",我們提醒他已經(jīng)發(fā)了n次"Hello"。接下來(lái)定義ClientData類來(lái)存儲(chǔ)用戶名以及他向服務(wù)器發(fā)送"Hello"的次數(shù)。

          1.?代碼
          1.?在EchoServer中創(chuàng)建一個(gè)EchoServerData類

          01 //---- EchoServerData.java ----

          02?package echoserver;

          03

          04 import org.quickserver.net.server.*;

          05 import java.io.*;

          06

          07 public class EchoServerData implements ClientData {

          08 private int helloCount;

          09 private String username;

          10

          11 public void setHelloCount(int count) {

          12 helloCount = count;

          13 }

          14 public int getHelloCount() {

          15 return helloCount;

          16 }

          17

          18 public void setUsername(String username) {

          19 this.username = username;

          20 }

          21 public String getUsername() {

          22 return username;

          23 }

          24 }

          25 //--- end of code ---


          2.?告訴QuickServer用這個(gè)EchoServerData來(lái)做為它的ClientData類。
          ??? 修改前面創(chuàng)建的EchoServer.java,代碼如下:

          01 package echoserver;

          02

          03 import org.quickserver.net.*;

          04 import org.quickserver.net.server.*;

          05

          06 import java.io.*;

          07

          08 public class EchoServer {

          09 public static void main(String s[]) {

          10

          11 String cmd = "echoserver.EchoCommandHandler";

          12 String auth = "echoserver.EchoServerQuickAuthenticator";

          13 String data = "echoserver.EchoServerData";

          14

          15 QuickServer myServer = new QuickServer(cmd);

          16 myServer.setAuthenticator(auth);

          17 myServer.setClientData(data);

          18

          19 myServer.setPort(4123);

          20 myServer.setName("Echo Server v 1.0");

          21 try {

          22 myServer.startServer();

          23 } catch(AppException e){

          24 System.out.println("Error in server : "+e);

          25 }

          26 }

          27 }


          ??? 上面的代碼中,我們將配置信息寫入String對(duì)象來(lái)設(shè)置QuickServer。???

          3.?修改Authenticator類,也就是EchoServerAuthenticator類,讓它在ClientData對(duì)象中存儲(chǔ)用戶名。下面是修改后的代碼:

          01 package echoserver;

          02

          03 import org.quickserver.net.server.*;

          04 import java.io.*;

          05

          06 public class EchoServerQuickAuthenticator extends QuickAuthenticator {

          07

          08 public boolean askAuthorisation(ClientHandler clientHandler)

          09 throws IOException {

          10 String username = askStringInput(clientHandler, "User Name :");

          11 if(username!=null && username.equalsIgnoreCase("QUIT")) {

          12 sendString(clientHandler, "Logged out.");

          13 //close the connection

          14 clientHandler.closeConnection();

          15 return false;

          16 }

          17

          18 String password = askStringInput(clientHandler, "Password :");

          19

          20 if(username==null || password ==null)

          21 return false;

          22

          23 if(username.equals(password)) {

          24 sendString(clientHandler, "Auth OK");

          25 //store the username in ClientData

          26 EchoServerData data = (EchoServerData)clientHandler.getClientData();

          27 data.setUsername(username);

          28 return true;

          29 } else {

          30 sendString(clientHandler, "Auth Failed");

          31 return false;

          32 }

          33 }

          34 }

          4.?修改ClientCommandHandler實(shí)現(xiàn)類EchoCommandHandler。如果用戶發(fā)送"Hello",給他一個(gè)問(wèn)候。如果他發(fā)送多次"Hello",告訴他已經(jīng)發(fā)送了n次"Hello"。下面是修改后的代碼:

          01 // EchoCommandHandler.java

          02 package echoserver;

          03

          04 import java.net.*;

          05 import java.io.*;

          06 import org.quickserver.net.server.ClientCommandHandler;

          07 import org.quickserver.net.server.ClientHandler;

          08

          09 public class EchoCommandHandler implements ClientCommandHandler {

          10

          11 public void gotConnected(ClientHandler handler)

          12 throws SocketTimeoutException, IOException {

          13 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

          14 handler.sendClientMsg("| Welcome to EchoServer v 1.0 |");

          15 handler.sendClientMsg("| Note: Password = Username |");

          16 handler.sendClientMsg("| Send 'Quit' to exit |");

          17 handler.sendClientMsg("+++++++++++++++++++++++++++++++");

          18 }

          19 public void lostConnection(ClientHandler handler)

          20 throws IOException {

          21 handler.sendSystemMsg("Connection lost : " +

          22 handler.getSocket().getInetAddress());

          23 }

          24 public void closingConnection(ClientHandler handler)

          25 throws IOException {

          26 handler.sendSystemMsg("Closing connection : " +

          27 handler.getSocket().getInetAddress());

          28 }

          29

          30 public void handleCommand(ClientHandler handler, String command)

          31 throws SocketTimeoutException, IOException {

          32 if(command.equals("Quit")) {

          33 handler.sendClientMsg("Bye ;-)");

          34 handler.closeConnection();

          35 } if(command.equalsIgnoreCase("hello")) {

          36 EchoServerData data = (EchoServerData) handler.getClientData();

          37 data.setHelloCount(data.getHelloCount()+1);

          38 if(data.getHelloCount()==1) {

          39 handler.sendClientMsg("Hello "+data.getUsername());

          40 } else {

          41 handler.sendClientMsg("You told Hello "+data.getHelloCount()+

          42 " times. ");

          43 }

          44 } else {

          45 handler.sendClientMsg("Echo : "+command);

          46 }

          47 }

          48 }


          5.?編譯改好的程序,運(yùn)行,使用SocketTest測(cè)試。登錄后,發(fā)送"Hello",系統(tǒng)會(huì)給一個(gè)問(wèn)候,再次發(fā)送"Hello",它將告訴你發(fā)送了多少次"Hello"。
          ?
          4.2?創(chuàng)建ClientData池

          ??? 現(xiàn)在我們知道ClientData可以正常工作了。但是對(duì)每一個(gè)連接QuickServer的客戶端都要?jiǎng)?chuàng)建一個(gè)新的ClientData對(duì)象,可能會(huì)造成性能上的瓶頸,尤其對(duì)性能要求較高的服務(wù)器來(lái)說(shuō)。
          ??? 我們可以創(chuàng)建一個(gè)ClientData池對(duì)象,無(wú)論客戶端什么時(shí)候進(jìn)行連接,都使用同一個(gè)對(duì)象。首先實(shí)現(xiàn)下面的接口:
          ??? org.quickserver.util.pool.PoolableObject
          ??? 查找QuickServer API文檔可以發(fā)現(xiàn)PoolableObject只有兩個(gè)必須實(shí)現(xiàn)的方法:
          ??? org.apache.commons.pool.PoolableObjectFactory屬于通常的工廠方法。
          ??? isPoolable()判斷對(duì)象是否可以成為池對(duì)象。

          PoolableObjectFactory
          org.apache.commons.pool.PoolableObjectFactory接口包含了以下方法:
          o?void activateObject(Object obj):重新初始化一個(gè)實(shí)例。
          o?void destroyObject(Object obj):銷毀一個(gè)不再需要的實(shí)例。
          o?Object makeObject():創(chuàng)建一個(gè)實(shí)例。
          o?void passivateObject(Object obj):禁止初始化一個(gè)實(shí)例。
          o?boolean validateObject(Object obj):確定一個(gè)實(shí)例是否安全。

          ??? 我們可以擴(kuò)展一個(gè)基于無(wú)操作的實(shí)現(xiàn)來(lái)創(chuàng)建可"池"化的對(duì)象:
          ??? org.apache.commons.pool.BasePoolableObjectFactory
          ??? 這個(gè)類只有一個(gè)抽象方法makeObject()和一個(gè)validateObject()方法,它只返回true。
          ??? 我們來(lái)創(chuàng)建一個(gè)EchoServerPoolableData類。

          01 //---- EchoServerPoolableData.java ----

          02 package echoserver;

          03

          04 import org.quickserver.net.server.*;

          05 import java.io.*;

          06

          07 public class EchoServerPoolableData

          08 extends EchoServerData

          09 implements org.apache.commons.pool.PoolableObjectFactory {

          10

          11 public void activateObject(Object obj) {

          12 }

          13 public void destroyObject(Object obj) {

          14 if(obj==null) return;

          15 passivateObject(obj);

          16 obj = null;

          17 }

          18 public Object makeObject() {

          19 return new EchoServerPoolableData();

          20 }

          21 public void passivateObject(Object obj) {

          22 EchoServerPoolableData pd = (EchoServerPoolableData)obj;

          23 pd.setHelloCount(0);

          24 pd.setUsername(null);

          25 }

          26 public boolean validateObject(Object obj) {

          27 if(obj==null)

          28 return false;

          29 else

          30 return true;

          31 }

          32 }

          33 //--- end of code ---

          ??? 這個(gè)類擴(kuò)展了我們的EchoServerData,然后我們實(shí)現(xiàn)了org.apache.commons.pool.BasePoolableObjectFactory,這個(gè)實(shí)現(xiàn)是簡(jiǎn)單的不需要解釋了。
          ??? 現(xiàn)在我們需要告訴QuickServer使用這個(gè)類來(lái)代替原來(lái)的ClientData類。
          ??????? myServer.setClientData("echoserver.EchoServerPoolableData");
          ??? 編譯修改的程序,可能會(huì)報(bào)如下錯(cuò)誤:
          ??????? package org.apache.commons.pool does not exist。
          ??? 這是因?yàn)榫幾g器不知道這個(gè)類??梢栽诃h(huán)境變量中添加D:\QuickServer\dist\commons-pool.jar包,并在運(yùn)行時(shí)
          ??? set classpath=%classpath%;d:\QuickServer\dist\QuickServer.jar; d:\QuickServer\dist\commons-pool.jar;.\(類所在文件夾)即可。

          posted on 2006-12-04 19:45 OMG 閱讀(1123) 評(píng)論(0)  編輯  收藏 所屬分類: Soket

          <2006年12月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          IT風(fēng)云人物

          文檔

          朋友

          相冊(cè)

          經(jīng)典網(wǎng)站

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 鄂伦春自治旗| 罗江县| 晴隆县| 南华县| 高清| 磐石市| 汤阴县| 辽宁省| 定远县| 讷河市| 博客| 南岸区| 泰安市| 延庆县| 德钦县| 集贤县| 娱乐| 苍梧县| 广宗县| 凤冈县| 灵寿县| 明光市| 永州市| 平陆县| 阜新市| 紫金县| 南郑县| 图片| 巴彦淖尔市| 竹溪县| 建水县| 阳山县| 南漳县| 枣阳市| 苏州市| 青田县| 霍州市| 通江县| 莱阳市| 青浦区| 明星|