




已阅读5页,还剩27页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
窗体顶端QuickServer开发手册(1)- 介绍 QuickServer是一个免费的开源Java库,用于快速创建健壮的多线程、多客户端TCP服务器应用程序。使用QuickServer,用户可以只集中处理应用程序的逻辑/协议,从而方便的建立功能强大的服务器应用。该程序由Akshathkumar Shetty设计和实现。 QuickServer安装目录下的example中有演示其功能的例子,最新的例子和文档可以通过网站 /或/获得。 该指南适用于所有想要学习和使用QuickServer的人,阅读该指南应具备基本的Java编程知识,基本的网络和sockets方面的知识也会有所帮助1.为什么需要QuickServer? 无论何种编程语言,socket编程对程序员来说都不是一件容易的事,创建多线程、多客户端的服务器socket更像一场恶梦了。在每个新的软件中处理多 socket连接,我们都要浪费大把时间编写大量重复的代码。QuickServer因而诞生使用Java创建多线程、多客户端服务器应用。2.基本构造QuickServer在应用逻辑上为开发者提供了四个类oClientCommandHandler 处理与客户端的交互使用字符串命令oClientObjectHandler 可选类 处理与客户端的交互使用对象命令oAuthenticator 可选类 客户端验证oClientData 可选类 客户端数据载体(支持类)下面的图表显示了QuickServer库的基本构造。QuickServer模块上七个辐条表示七个方法:ojava.lang.String info()oint getServiceState()oboolean initService(java.lang.Object config)oboolean startService()oboolean resumeService()oboolean suspendService()oboolean stopService() 与QuickServer模块相连接的四个组件中只有ClientCommandHandler是必须的。 QuickServerConfig对象由initService()方法构建。它实现了QuickServer,在读取XML配置后,QuickServerConfig用于QuickServer配置。 ClientHandler线程对象用于客户端缓冲池。可选的ClientData类与ClientHandler类关联,ClientHandler对 象容器参考ClientCommandHandler,ClientObjectHandler(可选),Authenticator(可选)对象包含在 QuickServer主函数中。 注意:上图中并未显示QSAdminServer,它是图中QuickServer的组成部分。3.主要特点o创建多线程、多客户端TCP服务器应用程序o支持安全服务的创建:SSL, TLSo清楚的分离服务、协议、验证逻辑oGUI图形界面远程管理支持oCommand Shell对服务器的本地管理o无须断开客户端连接的重启或延迟服务o为线程的再利用和大多数的使用对象建立缓冲池o完全的日志支持(Java构建)o支持发送和接收字符串、字节、二进制、序列化Java对象o在同样的xml中支持能够存贮指定应用数据的XML配置o支持通过IP地址限制服务o支持基于XML的JDBC映射o支持服务配置模式o支持从xml加载/重新加载用于jar包o在QuickServer中添加处理hookso指定允许的最大客户端连接数o在通常的TCP连接上支持谈判安全连接o支持鉴别和查询客户端o附带典型例子FTPServer, CmdServer,EchoWebServer, ChatServer4.1.4版的新功能o为QuickServer添加安全模式:SSL, TLSo添加SecureManagerLoader管理安全模式o在通常的TCP连接上添加谈判安全连接o添加初始化服务hookso为通信添加二进制模式o为QsAdminServer通信添加QSAdminAPIo为QuickServer 添加findAllClientByKeyo添加ConnectionLostException类o改进ClientHandler、安全配置o新例子XmlAdder:一个简单的xml服务,可添加两个整数o新例子PipeServer:一个简单的重定向服务窗体顶端QuickServer开发手册(2)- 安装 1. 运行环境QuickServer 1.2以上的版本需要(其实在偶看来一个1.4版以上JDK足矣): 推荐1.4版以上Java虚拟机,最低1.3版(未经测试). Java Logging API(下列之一)o java.util.logging包 JDK 1.4版自带o Lumberjack库 / XML 解析器 (下列之一)o SAX (面向XML 2.0的API) JDK 1.4版自带o JAXP (面向XML解析的Java API) 1.1 JDK 1.4版自带o Xerces /xerces2-jo Crimson /crimson Jakarta公共组件Digester, Poolo 这些产品包含在Apache开发的软件中(/)。Jar包都在以下的库中:BeanUtils, Collections, Logging. /commons/components.html. Apache软件许可证在文件“apache_license.txt”中。2. 安装 目前最新的1.4.1版QuickServer可在/download.html下载。安装QuickServer,假设安装路径为$INSTALL_PATH。 在CLASSPATH中添加$INSTALL_PATHdistQuickServer.jar,在PATH中添加$INSTALL_PATHbin。 另外测试socket的通讯软件推荐SockTest,在/soft/sockettest 可下载到最新版本。Windows自带的telnet也可以进行测试。QuickServer开发手册(3)- 构建EchoServer 学习怎样使用QuickServer库的一个好的方法是学习它提供的例子。在QuickServer安装路径下的examples文件夹里有许多典型的例子。 下面的章节里我们模仿其中的一个例子EchoServer来构建一个服务器。EchoServer是一个简单的TCP服务器,主要功能是将用户发送的字符串加上前缀Echo :后返回。虽然这个例子可用性不强,但它是一个对QuickServer所有特点的一个很好的示范。我们从构建一个最基本的服务器开始,以后慢慢给它添加新的功能。1.代码 首先实现EchoServer最基本的功能:将用户发送的字符串加上前缀Echo :后返回。 在本地创建一个文件夹存放需要的代码,如在c:projects中建立echoserver文件夹,然后创建一个类EchoServer.java:01 package echoserver;0203 import .*;04 import .server.*;0506 import java.io.*;0708 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行定义了一个QuickServer对象myServer,通过一个String对象 echoserver.EchoCommandHandler声明了要加载的类,这个类面向所有客户端做命令处理器,实现了 .server.ClientCommandHandler接口,我们即将创建。 第12行设置了一个服务器端口用来做监听,然后设置整个应用的名字(第13行)。最后启动服务(第15行)。 接下来为EchoServer创建一个实现.server.ClientCommandHandler接口的类EchoCommandHandler.java,用来处理服务器发送的命令。01 / EchoCommandHandler.java02 package echoserver;0304 import .*;05 import java.io.*;06 import .server.ClientCommandHandler;07 import .server.ClientHandler;0809 public class EchoCommandHandler implements ClientCommandHandler 1011 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 2829 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 根据QuickServer的要求,这个类必须实现ClientCommandHandler接口。 当客户端建立一个连接(11行),gotConnected()方法被调用。在这个方法里面,我们给客户端发送欢迎文本(13-16行),这些文本使用通 过ClientHandler的sendClientMsg()方法发送给客户端。我们也会使用ClientHandler的 sendSystemMessage()方法显示客户端连接的InetAddress(20-21,25-26行)。 handlerCommand()方法是ClientCommandHandler接口的核心方法,因为服务器接收客户端发送的任何命令时都要调用该方 法。在我们对这个方法的实现中,我们会检查命令是否为Quit(31行),如果是,我们将发送一些提示文本表示服务器即将关闭连接,然后关闭连接 (33行)。否则,将命令加上前缀Echo :返回给用户。2.运行和测试o运行命令提示符程序(cmd.exe)o进入代码所在文件夹根目录,如c:projectso编译代码 javac echoserver*.javao若无编译错误,运行服务器: set classpath=%classpath%;d:QuickServerdistQuickServer.jar;.(类所在文件夹) java echoserver.EchoServero您将会看到如下信息:o测试我们的服务器是否可以正常工作。再运行一个cmd程序,进入SocketTest.jar所在目录,键入java -jar sockettest.jar命令,弹出一个窗口。在IP Address中输入,在Port里输入4123,点击Connect按钮,将看到窗口中显示如下图的信息。 若使用telnet,可键入命令:open localhost 4123 在Message中输入一些字符串,点击Send按钮,浏览器将会返回一个加了前缀Echo :的字符串。发送Quit,服务器断开连接。QuickServer开发手册(4)- 添加认证 现在我们给刚刚创建的服务器添加认证功能。 查看.server.QuickServer的文档(docs文件夹下)你可以注意到里面有一个方法 public void setAuthenticator(java.lang.String authenticator) 阅读文档可知此方法中的authenticator字符串是实现.server.Authenticator接口的方法的全名。 Authenticator接口有两个实现: .server.QuickAuthenticator:这个类用来验证连接QuickServer的客户端。它只用一个实例处理所有的QuickServer验证。(推荐) .server.ServerAuthenticator:这个类同样用来验证连接QuickServer的客户端,但对每一个验证的处理都会创建一个实例。 接下来给EchoServer加验证功能。简单点,客户端输入的用户名和密码一致就算验证通过。 首先,在同样的文件夹里创建一个验证类:EchoServerQuickAuthenticator01 package echoserver;0203 import .server.*;04 import java.io.*;0506 public class EchoServerQuickAuthenticator extends QuickAuthenticator 0708 public boolean askAuthorisation(ClientHandler clientHandler)09 throws IOException 10 String username = askStringInput(clientHandler, User Name :);11 String password = askStringInput(clientHandler, Password :);1213 if(username=null | password =null)14 return false;1516 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 这个类扩展了.server.QuickAuthenticator(第6行),在 askAuthorisation()方法中(8行),通过askStringInput()方法要求客户端输入用户名和密码,并读入客户端输入的信息 (10-11行)。这个方法继承自QuickAuthenticator。如果用户名与密码相等,发送正确信息并返回true(16-18行),否则 发送错误信息并返回false(20-21行)。 接下来我们要告诉QuickServer使用我们新创建的验证类来做验证器。修改前一章创建的EchoServer.java文件,代码如下(粗体为修改的代码):01 package echoserver;0203 import .*;04 import .server.*;0506 import java.io.*;0708 public class EchoServer 0910 public static void main(String s) 1112 QuickServer myServer =13 new QuickServer(echoserver.EchoCommandHandler);14 myServer.setAuthenticator(15 echoserver.EchoServerQuickAuthenticator);16 myServer.setPort(4123);17 myServer.setName(EchoServer v 1.0);18 try 19 myServer.startServer();20 catch(AppException e)21 System.err.println(Error in server : +e);22 23 24 OK,将修改好的文件编译,按照前一章讲述的方法运行程序。这次当我们点击Connect时,浏览器会要求我们输入用户名和密码。如果输入的用户名和密码一致就可以登录。如果输入错误五次以上,浏览器会提示-ERR Max Auth Try Reached并自动断开连接。这个次数和提示信息可以通过QuickServer类的setMaxAuthTry() 和 setMaxAuthTryMsg()修改。 有时在验证过程中我们可能需要中途退出而不是等待验证结束,这时输入Quit是不起作用的。我们可以这样修改代码,有两个方法: 一是从EchoServerQuickAuthenticator类中的askAuthorisation()方法抛出一个.AppException异常,代码如下: String username = askStringInput(clientHandler, User Name :); if (username != null & username.equalsIgnoreCase(QUIT) sendString(clientHandler, Logged out.); throw new AppException(Quit); 或者参考ClientHandler,关闭连接,代码如下: String username = askStringInput(clientHandler, User Name :); if (username != null & username.equalsIgnoreCase(QUIT) sendString(clientHandler, Logged out.); clientHandler.closeConnection(); return false; ClientHandler对象能够提供很多客户端连接的有用信息,如IP地址。更多信息请参考API文档。注意: o 不要在验证器类中存贮任何客户端相关信息,如果需要,必须存放在ClientData类中-下一章将讲解该部分内容。 o 必须确认askAuthorisation()方法是线程安全的。QuickServer开发手册(5)- 客户数据 既然不能在ClientCommandHandler和ServerAuthenticator类中保存客户数据,我们使用ClientData类的handleCommand()或askAuthorisation()方法来存储所有的客户端信息。 示范一下这个特点有什么用。还是以EchoServer为例,当用户发送Hello时,我们给他一个问候。如果用户再发送Hello,我们提醒他已经发了n次Hello。接下来定义ClientData类来存储用户名以及他向服务器发送Hello的次数。1.代码1.在EchoServer中创建一个EchoServerData类01 /- EchoServerData.java -02package echoserver;0304 import .server.*;05 import java.io.*;0607 public class EchoServerData implements ClientData 08 private int helloCount;09 private String username;1011 public void setHelloCount(int count) 12 helloCount = count;13 14 public int getHelloCount() 15 return helloCount;16 1718 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用这个EchoServerData来做为它的ClientData类。 修改前面创建的EchoServer.java,代码如下:01 package echoserver;0203 import .*;04 import .server.*;0506 import java.io.*;0708 public class EchoServer 09 public static void main(String s) 1011 String cmd = echoserver.EchoCommandHandler;12 String auth = echoserver.EchoServerQuickAuthenticator;13 String data = echoserver.EchoServerData;1415 QuickServer myServer = new QuickServer(cmd);16 myServer.setAuthenticator(auth);17 myServer.setClientData(data);1819 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对象来设置QuickServer。 3.修改Authenticator类,也就是EchoServerAuthenticator类,让它在ClientData对象中存储用户名。下面是修改后的代码:01 package echoserver;0203 import .server.*;04 import java.io.*;0506 public class EchoServerQuickAuthenticator extends QuickAuthenticator 0708 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 connection14 clientHandler.closeConnection();15 return false;16 1718 String password = askStringInput(clientHandler, Password :);1920 if(username=null | password =null)21 return false;2223 if(username.equals(password) 24 sendString(clientHandler, Auth OK);25 /store the username in ClientData26 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实现类EchoCommandHandler。如果用户发送Hello,给他一个问候。如果他发送多次Hello,告诉他已经发送了n次Hello。下面是修改后的代码:01 / EchoCommandHandler.java02 package echoserver;0304 import .*;05 import java.io.*;06 import .server.ClientCommandHandler;07 import .server.ClientHandler;0809 public class EchoCommandHandler implements ClientCommandHandler 1011 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 2930 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.编译改好的程序,运行,使用SocketTest测试。登录后,发送Hello,系统会给一个问候,再次发送Hello,它将告诉你发送了多少次Hello。4.2创建ClientData池 现在我们知道ClientData可以正常工作了。但是对每一个连接QuickServer的客户端都要创建一个新的ClientData对象,可能会造成性能上的瓶颈,尤其对性能要求较高的服务器来说。 我们可以创建一个ClientData池对象,无论客户端什么时候进行连接,都使用同一个对象。首先实现下面的接口: org.quickserver.util.pool.PoolableObject 查找QuickServer API文档可以发现PoolableObject只有两个必须实现的方法: mons.pool.PoolableObjectFactory属于通常的工厂方法。 isPoolable()判断对象是否可以成为池对象。PoolableObjectFmons.pool.PoolableObjectFactory接口包含了以下方法:ovoid activateObject(Object obj):重新初始化一个实例。ovoid destroyObject(Object obj):销毁一个不再需要的实例。oObject makeObject():创建一个实例。ovoid passivateObject(Object obj):禁止初始化一个实例。oboolean validateObject(Object obj):确定一个实例是否安全。 我们可以扩展一个基于无操作的实现来创建可池化的对象: mons.pool.BasePoolableObjectFactory 这个类只有一个抽象方法makeObject()和一个validateObject()方法,它只返回true。 我们来创建一个EchoServerPoolableData类。01 /- EchoServerPoolableData.java -02 package echoserver;0304 import .server.*;05 import java.io.*;0607 public class EchoServerPoolableData08 extends EchoServerData09 implements mons.pool.PoolableObjectFactory 1011 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 else30 return true;31 32 33 /- end of code - 这个类扩展了我们的EchoServerData,然后我们实现了mons.pool.BasePoolableObjectFactory,这个实现是简单的不需要解释了。 现在我们需要告诉QuickServer使用这个类来代替原来的ClientData类。 myServer.setClientData(echoserver.EchoServerPoolableData); 编译修改的程序,可能会报如下错误: package mons.pool does not exist。 这是因为编译器不知道这个类。可以在环境变量中添加D:QuickServerdistcommons-pool.jar包,并在运行时 set classpath=%classpath%;d:QuickServerdistQuickServer.jar; d:QuickServerdistcommons-pool.jar;.(类所在文件夹)即可。QuickServer开发手册(6)- 远程管理支持我们的EchoServer可能需要修改几个服务器配置参数,如超时消息、最多验证数、最大验证时间。QuickServer支持这些功能而无须改变代码。1.使用QSAdminServer 当我们需要一个管理服务器来控制我们的服务器时,我们不需要修改代码甚至关闭正在运行的服务器。这项服务的实现类是: .qsadmin.QSAdminServer 要使用它的功能我们要调用QuickServer的startQSAdminServer()方法。QSAdminServer运行的默认端口是9876,我们可以使用下面两个方法之一修改它: setQSAdminServerPort(4124); getQSAdminServer().getServer().setPort(4124); 下面是能够在EchoServer 的4124端口运行QSAdminServer 的代码:01 package echoserver;0203 import .*;04 import .server.*;0506 import java.io.*;0708 public class EchoServer 09 public static void main(String s) 1011 String cmd = echoserver.EchoCommandHandler;12 String auth = echoserver.EchoServerQuickAuthenticator;13 String data = echoserver.EchoServerPoolableData; /Poolable1415 QuickServer myServer = new QuickServer(cmd);16 myServer.setAuthenticator(auth);17 myServer.setClientData(data);1819 myServer setPort(4123);20 myServer.setName(Echo Server v 1.0);2122 /config QSAdminServer23 myServer.setQSAdminServerPort(4124);24 myServer.getQSAdminServer().getServer().setName(EchoAdmin v 1.0);25 try 26 myServer.startQSAdminServer();27 myServer.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 甲方验收合格协议书范本
- 矿泉水客户销售合同范本
- 维修保养合同协议书范本
- 高端会所会员合同协议书
- 驻地企业抗疫协议书模板
- 麻蜥蜴养殖采购合同范本
- 银行与孵化器合作协议书
- 私人租地合同协议书范本
- 机动车抵押担保合同范本
- 电力数据采集协议书模板
- 女性导尿术方法步骤
- 农机安全事故典型案例分析
- 花店员工劳务合同协议
- 2025年人教版小学五年级下册奥林匹克数学竞赛试卷(附参考答案)
- DB22-T3309-2021-油莎豆生产技术规程-吉林省
- 2024年宁夏中卫公开招聘社区工作者考试试题答案解析
- 2025年国家心力衰竭诊断和治疗指南(完整版)
- 2025-2030中国煤炭机械行业发展分析及投资前景预测研究报告
- DL 5190.6-2012:电力建设施工技术规范 第6部分:水处理及制氢设备和系统
- 深度解析Palantir介绍
- 宠物公司创业路演
评论
0/150
提交评论