原貼地址:http://blog.csdn.net/clearwater21cn/category/99145.aspx
QuickServer開發(fā)指南(6)- 遠(yuǎn)程管理支持
我們的EchoServer可能需要修改幾個服務(wù)器配置參數(shù),如超時消息、最多驗證數(shù)、最大驗證時間。QuickServer支持這些功能而無須改變代碼。
1.?使用QSAdminServer??? 當(dāng)我們需要一個管理服務(wù)器來控制我們的服務(wù)器時,我們不需要修改代碼甚至關(guān)閉正在運行的服務(wù)器。這項服務(wù)的實現(xiàn)類是:
??? org.quickserver.net.qsadmin.QSAdminServer
??? 要使用它的功能我們要調(diào)用QuickServer的startQSAdminServer()方法。QSAdminServer運行的默認(rèn)端口是9876,我們可以使用下面兩個方法之一修改它:
??? setQSAdminServerPort(4124);
??? getQSAdminServer().getServer().setPort(4124);
??? 下面是能夠在EchoServer 的4124端口運行QSAdminServer 的代碼:
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.EchoServerPoolableData"; //Poolable 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 22 //config QSAdminServer 23 myServer.setQSAdminServerPort(4124); 24 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0"); 25 try { 26 myServer.startQSAdminServer(); 27 myServer.startServer(); 28 } catch(AppException e){ 29 System.out.println("Error in server : "+e); 30 } 31 } 32 } 33 |
??? 這樣,我們定義了我們的QSAdminServer運行在4124端口。但是它怎樣進(jìn)行驗證呢?如果沒有一個外在的驗證器,QSAdminServer將使用org.quickserver.net.qsadmin.Authenticator做為它的驗證器。查閱API文檔我們可以發(fā)現(xiàn)它非常簡單,用戶名和密碼都被硬編碼為:
??? 用戶名 : Admin
??? 密碼 : QsAdm1n
??? 現(xiàn)在讓我們編譯新的程序并運行之,控制臺將會輸出信息以說明服務(wù)器運行于4124端口。
??? 在QuickServer安裝目錄下的bin目錄下運行QsAdminGUI.bat,QsAdmin的界面如下所示

??? 現(xiàn)在可以連接到管理服務(wù)器了。點擊右上角的"Login"按鈕,將會彈出一個登錄對話框如下圖,輸入IP地址和服務(wù)器運行端口:127.0.0.1、4124,因為我們使用默認(rèn)的用戶名密碼,直接點擊"Login"登錄。
??? 登錄后界面將會顯示歡迎及登錄成功信息。現(xiàn)在可以選擇發(fā)送命令的目標(biāo)服務(wù)器(Target)及左邊一排命令按鈕所示的操作。
??? Target是基于發(fā)送命令的服務(wù)器,因為我們目前有兩個服務(wù)器EchoServer和EchoAdmin。
??? 界面右下邊有一個可以直接向服務(wù)器發(fā)送消息的文本框,命令可以參考QsAdmin command handler:
??? org.quickserver.net.qsadmin.CommandHandler API文檔
??? 若想要改變服務(wù)器的配置,可以點選"Get/Set"書簽,只要選擇"Target",點擊"Reload Properties For The Target"以重新加載目標(biāo)服務(wù)器的配置。修改好參數(shù),然后點擊"Save"就可以了。部分參數(shù)的生效需要重啟服務(wù)器,不過這樣不會斷開與客戶端的連接。
2.?添加自己的命令??? 前面講過如果我們想改變一些服務(wù)器的屬性,我們無須修改已有的代碼或重啟服務(wù)器,我們可以添加自己的命令來管理服務(wù)器。
??? 讓我們用一個例子來演示這個功能。當(dāng)用戶發(fā)送"What's interest"(利息是多少)時,我們將要顯示當(dāng)前的利率。這個數(shù)字存貯在一個對象中,如果需要的話,無須重啟服務(wù)器就可以改變它。我們說它是可變的并且當(dāng)服務(wù)器運行時我們需要改變它。
??? 我們來實現(xiàn)command handler以顯示利率。首先要改變EchoServer和command handler。下面是代碼:
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.EchoServerPoolableData"; //Poolable 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 22 //store data needed to be changed by QSAdminServer 23 Object[] store = new Object[]{"12.00"}; 24 myServer setStoreObjects(store); 25 26 //config QSAdminServer 27 myServer.setQSAdminServerPort(4124); 28 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0"); 29 try { 30 myServer.startQSAdminServer(); 31 myServer.startServer(); 32 } catch(AppException e){ 33 System.out.println("Error in server : "+e); 34 }
35 } 36 } 37 |
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 return; 36 } 37 if(command.equals("What's interest?")) { 38 handler.sendClientMsg("Interest is : "+ 39 (String)handler.getServer().getStoreObjects()[0]+ 40 "%");
41 } else if(command.equalsIgnoreCase("hello")) { 42 EchoServerData data = (EchoServerData) handler.getClientData(); 43 data.setHelloCount(data.getHelloCount()+1); 44 if(data.getHelloCount()==1) { 45 handler.sendClientMsg("Hello "+data.getUsername()); 46 } else { 47 handler.sendClientMsg("You told Hello "+data.getHelloCount()+ 48 " times. "); 49 } 50 } else { 51 handler.sendClientMsg("Echo : "+command); 52 } 53 } 54 } |
??? 接下來為QSAdminServer 添加Command插件
01 package echoserver; 02 03 04 import java.io.*; 05 import java.net.SocketTimeoutException; 06 import org.quickserver.net.server.*; 07 import org.quickserver.net.qsadmin.*; 08 09 public class QSAdminCommandPlugin implements CommandPlugin { 10 /** 11 * Echoserver commands 12 * ---------------------------------- 13 * set interest value 14 * get interest 15 */ 16 public boolean handleCommand(ClientHandler handler, String command) 17 throws SocketTimeoutException, IOException { 18 19 QuickServer echoserver = (QuickServer) 20 handler.getServer().getStoreObjects()[0]; 21 Object obj[] = echoserver.getStoreObjects(); 22 23 if(command.toLowerCase().startsWith("set interest ")) { 24 String temp = ""; 25 temp = command.substring("set interest ".length()); 26 obj[0] = temp; 27 echoserver.setStoreObjects(obj); 28 handler.sendClientMsg("+OK interest changed"); 29 return true;
30 } else if(command.toLowerCase().equals("get interest")) { 31 handler.sendClientMsg("+OK " + (String)obj[0]); 32 return true; 33 } 34 //ask QSAdminServer to process the command 35 return false; 36 } 37 } |
??? 在上面的代碼中,我們使用下面的代碼調(diào)用了EchoServer的QSAdminServer中的存貯對象。(參考QuickServer API 文檔中的QSAdminServer和CommandPlugin部分)。
??? QuickServer echoserver = (QuickServer)handler.getServer().getStoreObjects()[0];
??? 如果進(jìn)程獲得了一個命令,返回true,否則返回false,并指明QSAdminServer的默認(rèn)命令處理器將被用來處理命令。同樣的技術(shù)將被使用于覆寫QSAdminServer命令處理器的默認(rèn)命令。
??? 讓我們告訴QuickServer這個類是QSAdminServer的Command插件。修改后的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.EchoServerPoolableData"; //Poolable 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 22 //store data needed to be changed by QSAdminServer 23 Object[] store = new Object[]{"12.00"}; 24 myServer.setStoreObjects(store); 25 26 //config QSAdminServer 27 myServer.setQSAdminServerPort(4124); 28 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0");
29 try { 30 //add command plugin 31 myServer.getQSAdminServer().setCommandPlugin( 32 "echoserver.QSAdminCommandPlugin"); 33 myServer startQSAdminServer(); 34 myServer.startServer(); 35 } catch(AppException e){ 36 System.out.println("Error in server : "+e); 37 } catch(Exception e){ 38 System.out.println("Error : "+e); 39 } 40 } 41 } |
??? 編譯代碼,并運行。現(xiàn)在打開客戶端如SocketTest,發(fā)送命令"What's interest?",將顯示"Interest is : 12.00%"。
??? 運行QSAdminGUI,在發(fā)送消息框中鍵入以下命令,發(fā)送:
??? get interest
??? 系統(tǒng)輸出"+OK 12.00"
??? 現(xiàn)在把這個參數(shù)修改一下,發(fā)送下面的命令
??? ?set interest 15.00
??? 系統(tǒng)輸出"+OK interest changed"
??? 再次在客戶端發(fā)送命令"What's interest?",客戶端顯示"Interest is : 15.00%"。
QuickServer開發(fā)指南(7)- 使用和定制日志對任何一個項目來說,日志都是一個重要的工具。日志幫助我們?nèi)ダ斫馕覀兊捻椖績?nèi)部發(fā)生了什么,它也會提供審核和調(diào)試信息。想要知道更多有關(guān)日志的資料可查閱Sun公司的網(wǎng)站
???
http://java.sun.com/j2se/1.4.0/docs/guide/util/logging/overview.html??? QuickServer目前只支持Java Logging API (java.util.logging)。1.4版的Java已加入logging。如果你還在使用舊的版本,你可以安裝Lumberjack庫提供的可選的實現(xiàn)(
http://javalogging.sourceforge.net/)。
??? 讓我們給我們的EchoServer做一個日志器。QuickServer默認(rèn)已可以使用日志器,但是除了ConsoleHandler和設(shè)置INFO的級別之外它什么也沒有處理。因而無論何時我們在EchoServer關(guān)閉和客戶端的連接,我們都會在控制臺看見一些相似的信息
??????? Feb 16, 2000 10:11:25 PM ClientHandler sendSystemMsg
??????? INFO: Closing connection : /127.0.0.1
??? 上面的信息指明IP為127.0.0.1的客戶端關(guān)閉了連接。這條消息的顯示使用了ClientHalder類的sendSystemMsg()方法.
??? 讓我們看看我們怎樣在我們的項目中控制日志。使用java logging必須先在類中導(dǎo)入java.util.logging包。
??? 從上面的日志,我們發(fā)現(xiàn)某些客戶端關(guān)閉了連接或掉線,但是它是怎樣顯示的,我們并沒有寫任何有關(guān)日志的命令。它會顯示是因為QuickServer使用了內(nèi)部的日志器ClientHandler類的sendSystemMsg()方法。
??? 查看QuickServer文檔可以找到sendSystemMsg(),如果沒有指定級別,它默認(rèn)使用INFO。你可以在ClientCommandHandler或Authenticator或任何類中使用sendSystemMsg()來記錄一個事件。
1.?簡單的日志?? 現(xiàn)在我們來記錄每一個連接EchoServer的客戶端IP地址。編輯EchoCommandHandler.java文件。在gotConnected(ClientHandler handler)后添加
??? handler.sendSystemMsg("New Client : " +
????????????????????????? handler.getSocket().getInetAddress().getHostAddress(),
????????????????????????? Level.INFO);
?? 還要導(dǎo)入包import java.util.logging.*;
?? 編譯并運行,連接到EchoServer,你將看到當(dāng)客戶端連接時控制臺會顯示你的地址。
?? 讓QuickServer將日志記錄到文件中(XML格式)。下面是修改的文件:
01 package echoserver; 02 03 import org.quickserver.net.*; 04 import org.quickserver.net.server.*; 05 06 import java.io.*; 07 import java.util.logging.*; 08 09 public class EchoServer { 10 public static void main(String s[]) { 11 12 String cmd = "echoserver.EchoCommandHandler"; 13 String auth = "echoserver.EchoServerQuickAuthenticator"; 14 String data = "echoserver.EchoServerPoolableData"; //Poolable 15 16 QuickServer myServer = new QuickServer(); 17 18 //setup logger to log to file 19 Logger logger = null; 20 FileHandler xmlLog = null; 21 File log = new File("./log/"); 22 if(!log.canRead()) 23 log.mkdir(); 24 try { 25 logger = Logger.getLogger(""); //get root logger 26 logger.setLevel(Level.INFO); 27 xmlLog = new FileHandler("log/EchoServer.xml");
28 logger.addHandler(xmlLog); 29 } catch(IOException e){ 30 System.err.println("Could not create xmlLog FileHandler : "+e); 31 } 32 //set logging level to fine 33 myServer setConsoleLoggingLevel(Level INFO); 34 35 36 myServer.setClientCommandHandler(cmd); 37 myServer.setAuthenticator(auth); 38 myServer.setClientData(data); 39 40 myServer.setPort(4123); 41 myServer.setName("Echo Server v 1.0"); 42 43 //store data needed to be changed by QSAdminServer 44 Object[] store = new Object[]{"12.00"}; 45 myServer.setStoreObjects(store); 46 47 //config QSAdminServer 48 myServer.setQSAdminServerPort(4124); 49 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0"); 50 try { 51 //add command plugin 52 myServer.getQSAdminServer().setCommandPlugin( 53 "echoserver.QSAdminCommandPlugin"); 54 myServer.startQSAdminServer(); 55 myServer.startServer(); 56 } catch(AppException e){ 57 System.out.println("Error in server : "+e); 58 } catch(Exception e){ 59 System.out.println("Error : "+e); 60 } 61 } 62 } |
??? 在上面的代碼中,我們首先檢查是否存在一個日志文件夾(21、22行),如果沒有先創(chuàng)建它。
??? 在25行,我們嘗試獲得一個日志器,28行,添加一個新的FileHandler,這里我們沒有指定格式因為默認(rèn)的格式就是XML的。
??? 在33行,我們設(shè)置日志的控制級別為INFO。
??? 接下來修改EchoCommandHandler.java
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 import java.util.logging.*; 09 10 public class EchoCommandHandler implements ClientCommandHandler { 11 12 public void gotConnected(ClientHandler handler) 13 throws SocketTimeoutException, IOException { 14 handler.sendSystemMsg("New Client : "+ 15 handler.getSocket().getInetAddress().getHostAddress(), 16 Level.INFO); 17 handler.sendClientMsg("+++++++++++++++++++++++++++++++"); 18 handler.sendClientMsg("| Welcome to EchoServer v 1.0 |"); 19 handler.sendClientMsg("| Note: Password = Username |"); 20 handler.sendClientMsg("| Send 'Quit' to exit |"); 21 handler.sendClientMsg("+++++++++++++++++++++++++++++++"); 22 } 23 public void lostConnection(ClientHandler handler) 24 throws IOException { 25 handler.sendSystemMsg("Connection lost : " + 26 handler.getSocket().getInetAddress()); 27 } 28 public void closingConnection(ClientHandler handler) 29 throws IOException { 30 handler.sendSystemMsg("Closing connection : " + 31 handler.getSocket().getInetAddress()); 32 } 33 34 public void handleCommand(ClientHandler handler, String command) 35 throws SocketTimeoutException, IOException { 36 if(command.equals("Quit")) { 37 handler.sendClientMsg("Bye ;-)"); 38 handler.closeConnection(); 39 return; 40 } 41 if(command.equals("What's interest?")) { 42 handler.sendClientMsg("Interest is : "+ 43 (String)handler.getServer().getStoreObjects()[0]+ 44 "%"); 45 } else if(command.equalsIgnoreCase("hello")) { 46 EchoServerData data = (EchoServerData) handler.getClientData(); 47 data.setHelloCount(data.getHelloCount()+1); 48 if(data.getHelloCount()==1) { 49 handler.sendClientMsg("Hello "+data.getUsername()); 50 } else { 51 handler.sendClientMsg("You told Hello "+data.getHelloCount()+ 52 " times. "); 53 } 54 } else { 55 handler.sendClientMsg("Echo : "+command); 56 } 57 } 58 } |
??? 編譯并運行程序,現(xiàn)在嘗試連接,你將看到它會同時在控制臺和xml文件記錄你的IP地址。
??? 讓我們使用QSAdminGUI設(shè)置日志級別為FINEST,觀察日志內(nèi)容的變化。日志記錄增加了。另外一個改變?nèi)罩炯墑e的方法是修改代碼,可以使用logger.setLevel()或者QuickServer的方法setLoggingLevel()來設(shè)置所有句柄的日志級別。
2.?日志的高級應(yīng)用??? 當(dāng)我們設(shè)置日志級別為FINEST時,會記錄很多信息。一個可能的需要是分離QuickServer和應(yīng)用的日志。下面的代碼允許你這么做。
01 package echoserver; 02 03 import org.quickserver.net.*; 04 import org.quickserver.net.server.*; 05 06 import java.io.*; 07 import java.util.logging.*; 08 09 public class EchoServer { 10 public static void main(String s[]) { 11 12 String cmd = "echoserver.EchoCommandHandler"; 13 String auth = "echoserver.EchoServerQuickAuthenticator"; 14 String data = "echoserver.EchoServerPoolableData"; //Poolable 15 16 QuickServer myServer = new QuickServer(); 17 18 //setup logger to log to file 19 Logger logger = null; 20 FileHandler xmlLog = null; 21 FileHandler txtLog = null;
22 File log = new File("./log/"); 23 if(!log.canRead()) 24 log.mkdir(); 25 try { 26 logger = Logger.getLogger("org.quickserver.net"); //get QS logger 27 logger.setLevel(Level.FINEST); 28 xmlLog = new FileHandler("log/EchoServer.xml"); 29 logger.addHandler(xmlLog); 30 31 logger = Logger.getLogger("echoserver"); //get App logger 32 logger.setLevel(Level.FINEST); 33 txtLog = new FileHandler("log/EchoServer.txt"); 34 txtLog.setFormatter(new SimpleFormatter()); 35 logger.addHandler(txtLog); 36 myServer.setAppLogger(logger); //img : Sets logger to be used for app. 37 } catch(IOException e){ 38 System.err.println("Could not create xmlLog FileHandler : "+e); 39 } 40 //set logging level to fine 41 myServer.setConsoleLoggingLevel(Level.INFO); 42 43 44 myServer.setClientCommandHandler(cmd); 45 myServer.setAuthenticator(auth); 46 myServer.setClientData(data); 47 48 myServer.setPort(4123); 49 myServer.setName("Echo Server v 1.0"); 50 51 //store data needed to be changed by QSAdminServer 52 Object[] store = new Object[]{"12.00"}; 53 myServer.setStoreObjects(store); 54 55 //config QSAdminServer 56 myServer.setQSAdminServerPort(4124); 57 myServer.getQSAdminServer().getServer().setName("EchoAdmin v 1.0"); 58 try { 59 //add command plugin 60 myServer.getQSAdminServer().setCommandPlugin( 61 "echoserver.QSAdminCommandPlugin"); 62 myServer.startQSAdminServer(); 63 myServer.startServer(); 64 } catch(AppException e){ 65 System.out.println("Error in server : "+e); 66 } catch(Exception e){ 67 System.out.println("Error : "+e); 68 } 69 } 70 } |
??? 代碼中的注釋說明的很清楚了。編譯并運行,連接后你將看見QuickServer內(nèi)部的日志記錄到了xml文件,應(yīng)用級別的日志記錄到了我們想要的txt文件。
注意:??? 要盡量減少控制臺中的日志數(shù)量,使用文件記錄詳細(xì)的日志,并降低日志的級別。這樣可以改善應(yīng)用的性能。避免使用System.out.println(),用logging代替。ClientHandler中的sendSystemMsg()方法在記錄日志方面很有用。
QuickServer開發(fā)指南(8)- XML配置
在前面的章節(jié)里我們擴(kuò)展了EchoServer。我們已經(jīng)在類中配置了QuickServer,在某些情況下這是可接受的。但是很多應(yīng)用更希望用戶能夠在應(yīng)用啟動后動態(tài)配置應(yīng)用。給QuickServer添加這方面功能,你可以告訴服務(wù)器讀取XML文件并實例化它。
??? 要配置QuickServer首先要寫配置文件,然后告訴QuickServer加載這個配置。下面是一個非常簡單的配置文件
??? <quickserver>
??????? <name>EchoServer v 1.0</name>
??????? <client-command-handler>
??????????? echoserver.EchoCommandHandler
??????? </client-command-handler>
??? </quickserver>
??? 現(xiàn)在有兩種方式啟動服務(wù)器 - 使用QuickServer啟動參數(shù)--load
在這里你要做的是在啟動QuickServer時使用"-load"指定xml配置文件的路徑。例如
java -jar QuickServer.jar -load myxmlconfig.xml
或
java org.quickserver.net.server.QuickServer -load myxmlconfig.xml
或
quickserver.bat -load myxmlconfig.xml
- 使用QuickServer的initService()方法
有時你可能需要在啟動你的應(yīng)用時使用自己的jar文件或類文件,或者你可能想要在啟動前添加一些代碼,那么這個選擇是最合適的。下面的代碼通過xml配置文件初始化了QuickServer。
QuickServer myServer = new QuickServer();
//pick the xml file form config folder
String confFile = "conf" + File.separator + "MyServer.xml";
Object config[] = new Object[] {confFile};
if(myServer.initService(config) != true) {
System.err.println("Could't init server !!");
}
現(xiàn)在我們來給我們的EchoServer寫配置文件。下面是XML文件
01 <quickserver> 02 <name>EchoServer v 1.0</name> 03 <port>4123</port> 04 <bind-address>127.0.0.1</bind-address> 05 06 <client-command-handler> 07 echoserver.EchoCommandHandler 08 </client-command-handler> 09 <authenticator> 10 echoserver.EchoServerQuickAuthenticator 11 </authenticator> 12 <client-data> 13 echoserver.EchoServerPoolableData 14 </client-data> 15 16 <console-logging-level>INFO</console-logging-level> 17 18 <!-- some extra config. added just to show --> 19 <timeout>4</timeout> 20 <timeout-msg>-ERR Timeout</timeout-msg> 21 <max-auth-try>5</max-auth-try> 22 <max-auth-try-msg>-ERR Max Auth Try Reached</max-auth-try-msg> 23 <max-connection>-1</max-connection> 24 <max-connection-msg> 25 Server Busy\nMax Connection Reached 26 </max-connection-msg> 27 <object-pool> 28 <max-active>-1</max-active> 29 <max-idle>15</max-idle> 30 </object-pool> 31 <!-- some extra config. added just to show --> 32 33 <qsadmin-server> 34 <name>EchoAdmin v 1.0</name> 35 <port>4124</port> 36 <bind-address>127.0.0.1</bind-address> 37 <command-plugin> 38 echoserver.QSAdminCommandPlugin 39 </command-plugin> 40 </qsadmin-server> 41 42 </quickserver> |
下面是修改過的EchoServer.java文件,它現(xiàn)在可以從xml文件加載配置
01 package echoserver; 02 03 import org.quickserver.net.*; 04 import org.quickserver.net.server.*; 05 06 import java.io.*; 07 import java.util.logging.*; 08 09 public class EchoServer { 10 public static void main(String s[]) { 11 12 QuickServer myServer = new QuickServer(); 13 14 //setup logger to log to file 15 Logger logger = null; 16 FileHandler xmlLog = null; 17 FileHandler txtLog = null; 18 File log = new File("./log/"); 19 if(!log.canRead()) 20 log.mkdir(); 21 try { 22 logger = Logger.getLogger("org.quickserver.net"); //get qs logger 23 logger.setLevel(Level.FINEST); 24 xmlLog = new FileHandler("log/EchoServer.xml"); 25 logger.addHandler(xmlLog); 26 27 logger = Logger.getLogger("echoserver"); //get app logger 28 logger.setLevel(Level.FINEST); 29 txtLog = new FileHandler("log/EchoServer.txt"); 30 txtLog.setFormatter(new SimpleFormatter()); 31 logger.addHandler(txtLog); 32 //img : Sets logger to be used for app. 33 myServer.setAppLogger(logger); 34 } catch(IOException e){ 35 System.err.println("Could not create xmlLog FileHandler : "+e); 36 } 37 38 //store data needed to be changed by QSAdminServer 39 Object[] store = new Object[]{"12.00"}; 40 myServer.setStoreObjects(store); 41 42 //load QuickServer from xml
43 String confFile = "config"+File.separator+"EchoServer.xml"; 44 Object config[] = new Object[] {confFile}; 45 if(myServer.initService(config) == true) { 46 try { 47 myServer.startQSAdminServer(); 48 myServer.startServer(); 49 } catch(AppException e){ 50 System.out.println("Error in server : "+e); 51 } catch(Exception e){ 52 System.out.println("Error : "+e); 53 } 54 } 55 } 56 } 57 |
??? 想要知道更多的XML配置請參考QuickServer Java文檔(主頁有一個xml樣本)以及QuickServer提供的例子。
QuickServer開發(fā)指南(9)- 數(shù)據(jù)模式和數(shù)據(jù)類型
直到現(xiàn)在我們的通信還是僅僅在使用以<CR><LF>結(jié)尾的字符串。當(dāng)然,在Internet標(biāo)準(zhǔn)協(xié)議里它是最常用的。但有時我們可能需要接收字節(jié)流或Java對象。
??? 下面是數(shù)據(jù)模式和數(shù)據(jù)類型,使用它你可以告訴ClientHandler使用哪一種通信模式。
??? 數(shù)據(jù)模式用于定義QuickServer和客戶Socket之間的數(shù)據(jù)交換格式。下面是目前支持的三種模式:
- DataMode.STRING - 這是默認(rèn)的交換模式,在這種模式下你可以接收字符串?dāng)?shù)據(jù)(以<CR><LF>結(jié)尾)
- ?DataMode.OBJECT - 在這種模式里你可以接收可序列化的Java對象。這種模式僅僅使用在客戶端可以寫java的情況下。
- ?DataMode.BYTE - 在這種模式下你可以接收客戶端發(fā)送的所有字節(jié),包括<CR>或<LF>或任何其它控制字符。這種模式在處理基于客戶機(jī)或無標(biāo)準(zhǔn)協(xié)議如xml或你自己定義的協(xié)議的硬件時非常有用。
數(shù)據(jù)類型用戶定義QuickServer和客戶Socket之間的數(shù)據(jù)交換類型。目前有兩種格式:
- DataType.IN - 指定數(shù)據(jù)為輸入QuickServer的數(shù)據(jù)。
- DataType.OUT - 指定數(shù)據(jù)為從QuickServer輸出的數(shù)據(jù)。
??? 任何數(shù)據(jù)類型的數(shù)據(jù)模式都可以使用ClientHandler的setDataMode()方法設(shè)置,格式如下
??? setDataMode(DataMode dataMode, DataType dataType)
注意:
??? 當(dāng)模式為DataMode.OBJECT類型為DataType.IN,調(diào)用將會阻塞,直到客戶端的ObjectOutputStream被寫和頭被刷新。
posted on 2006-12-04 19:49
OMG 閱讀(1908)
評論(0) 編輯 收藏 所屬分類:
Soket