看下面的这段代码,摘自《Java Examples in a Nutsbell》(java实例技术手册):
就是一个简单的通用的多线程服务器
这个例子可以通过配置参数:
java je3.net.Server -control www 3333 je3.net.Server$HTTPMirror 5555
来启动,然后再ie中输入: http://localhost:5555就可以看到效果。
写一个policy文件放在同根目录下:叫server.policy
grant{
permission java.net.SocketPermission "*:1024-4444","connect,accept";
permission java.io.FilePermission "E://workspace//j2ee1.3//-", "read";
};
下面加上jvm虚拟机参数
java -Djava.security.manager -Djava.security.policy=server.policy
je3.net.Server -control www 3333 je3.net.Server$HTTPMirror 5555再次启动。
按道理,本不应该启动。因为端口5555并没有得到连接许可。但是很可惜输入 http://localhost:5555还是可以看到结果。因为在java的sdk中暗含了java.policy文件。那就把它改为-Djava.security.policy==server.policy应该就可以了。结果跑不了了。原因就在policy文件中的permission java.net.SocketPermission "*:1024-4444","connect,accept";其实,我一直不太清楚listen ,accept,connect的区别在什么地方。但是这里的例子说明你只用permission java.net.SocketPermission "*:1024-4444","listen";就可以了。端口该闭的就闭了。如果用accept和connect反而没有什么用。不知道java的安全性高在什么地方。因为java.policy文件中从1024以上的端口全都使用了listen。所以以后要配置端口时一定要注意。
/**/
/*
*Copyright(c)2004DavidFlanagan.Allrightsreserved.
*ThiscodeisfromthebookJavaExamplesinaNutshell,3ndEdition.
*ItisprovidedAS-IS,WITHOUTANYWARRANTYeitherexpressedorimplied.
*Youmaystudy,use,andmodifyitforanynon-commercialpurpose,
*includingteachinganduseinopen-sourceprojects.
*Youmaydistributeitnon-commerciallyaslongasyouretainthisnotice.
*Foracommercialuselicense,ortopurchasethebook,
*pleasevisithttp://www.davidflanagan.com/javaexamples3.
*/
package
je3.net;
import
java.io.
*
;
import
java.net.
*
;
import
java.util.
*
;
import
java.util.logging.
*
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/***/
/**
*Thisclassisagenericframeworkforaflexible,multi-threadedserver.
*Itlistensonanynumberofspecifiedports,and,whenitreceivesa
*connectiononaport,passesinputandoutputstreamstoaspecifiedService
*objectwhichprovidestheactualservice.Itcanlimitthenumberof
*concurrentconnections,andlogsactivitytoaspecifiedstream.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
Server
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Amain()methodforrunningtheserverasastandaloneprogram.The
*command-lineargumentstotheprogramshouldbepairsofservicenames
*andportnumbers.Foreachpair,theprogramwilldynamicallyloadthe
*namedServiceclass,instantiateit,andtelltheservertoprovide
*thatServiceonthespecifiedport.Thespecial-controlargument
*shouldbefollowedbyapasswordandport,andwillstartspecial
*servercontrolservicerunningonthespecifiedport,protectedbythe
*specifiedpassword.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticvoidmain(String[]args)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
if(args.length<2)//Checknumberofarguments
thrownewIllegalArgumentException("Mustspecifyaservice");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Createaserverobjectthathasalimitof10concurrent
//connections,andlogstoaLoggerattheLevel.INFOlevel
//PriortoJava1.4wedidthis:newServer(System.out,10);
Servers=newServer(Logger.getLogger(Server.class.getName()),
Level.INFO,10);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Parsetheargumentlist
inti=0;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(i<args.length)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(args[i].equals("-control"))...{//Handlethe-controlarg
i++;
Stringpassword=args[i++];
intport=Integer.parseInt(args[i++]);
//addcontrolservice
s.addService(newControl(s,password),port);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{
//Otherwisestartanamedserviceonthespecifiedport.
//DynamicallyloadandinstantiateaServiceclass
StringserviceName=args[i++];
ClassserviceClass=Class.forName(serviceName);
Serviceservice=(Service)serviceClass.newInstance();
intport=Integer.parseInt(args[i++]);
s.addService(service,port);
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(Exceptione)...{//Displayamessageifanythinggoeswrong
System.err.println("Server:"+e);
System.err.println("Usage:javaServer"+
"[-control<password><port>]"+
"[<servicename><port>...]");
System.exit(1);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Thisisthestatefortheserver
Mapservices;//HashtablemappingportstoListeners
Setconnections;//Thesetofcurrentconnections
intmaxConnections;//Theconcurrentconnectionlimit
ThreadGroupthreadGroup;//Thethreadgroupforallourthreads
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Thisclasswasoriginallywrittentosendloggingoutputtoastream.
//Ithasbeenretrofittedtoalsosupportthejava.util.loggingAPIof
//Java1.4.Youcanuseeither,neither,orboth.
PrintWriterlogStream;//Wherewesendourloggingoutputto
Loggerlogger;//AJava1.4loggingdestination
LevellogLevel;//theleveltologmessagesat
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisistheServer()constructor.Itmustbepassedastream
*tosendlogoutputto(maybenull),andthelimitonthenumberof
*concurrentconnections.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicServer(OutputStreamlogStream,intmaxConnections)...{
this(maxConnections);
setLogStream(logStream);
log("Startingserver");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisconstructoraddedtosupportloggingwiththeJava1.4Loggerclass
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicServer(Loggerlogger,LevellogLevel,intmaxConnections)...{
this(maxConnections);
setLogger(logger,logLevel);
log("Startingserver");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisconstructorsupportsnologging
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicServer(intmaxConnections)...{
threadGroup=newThreadGroup(Server.class.getName());
this.maxConnections=maxConnections;
services=newHashMap();
connections=newHashSet(maxConnections);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Apublicmethodtosetthecurrentloggingstream.Passnull
*toturnloggingoff.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedvoidsetLogStream(OutputStreamout)...{
if(out!=null)logStream=newPrintWriter(out);
elselogStream=null;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*SetthecurrentLoggerandlogginglevel.Passnulltoturnloggingoff.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedvoidsetLogger(Loggerlogger,Levellevel)...{
this.logger=logger;
this.logLevel=level;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**Writethespecifiedstringtothelog*/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
protectedsynchronizedvoidlog(Strings)...{
if(logger!=null)logger.log(logLevel,s);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(logStream!=null)...{
logStream.println("["+newDate()+"]"+s);
logStream.flush();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**Writethespecifiedobjecttothelog*/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
protectedvoidlog(Objecto)...{log(o.toString());}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thismethodmakestheserverstartprovidinganewservice.
*ItrunsthespecifiedServiceobjectonthespecifiedport.
**/
publicsynchronizedvoidaddService(Serviceservice,intport)
throwsIOException
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
Integerkey=newInteger(port);//thehashtablekey
//Checkwhetheraserviceisalreadyonthatport
if(services.get(key)!=null)
thrownewIllegalArgumentException("Port"+port+
"alreadyinuse.");
//CreateaListenerobjecttolistenforconnectionsontheport
Listenerlistener=newListener(threadGroup,port,service);
//Storeitinthehashtable
services.put(key,listener);
//Logit
log("Startingservice"+service.getClass().getName()+
"onport"+port);
//Startthelistenerrunning.
listener.start();
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thismethodmakestheserverstopprovidingaserviceonaport.
*Itdoesnotterminateanypendingconnectionstothatservice,merely
*causestheservertostopacceptingnewconnections
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedvoidremoveService(intport)...{
Integerkey=newInteger(port);//hashtablekey
//LookuptheListenerobjectfortheportinthehashtable
finalListenerlistener=(Listener)services.get(key);
if(listener==null)return;
//Askthelistenertostop
listener.pleaseStop();
//Removeitfromthehashtable
services.remove(key);
//Andlogit.
log("Stoppingservice"+listener.service.getClass().getName()+
"onport"+port);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisnestedThreadsubclassisa"listener".Itlistensfor
*connectionsonaspecifiedport(usingaServerSocket)andwhenitgets
*aconnectionrequest,itcallstheserversaddConnection()methodto
*accept(orreject)theconnection.ThereisoneListenerforeach
*ServicebeingprovidedbytheServer.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicclassListenerextendsThread...{
ServerSocketlisten_socket;//Thesockettolistenforconnections
intport;//Theportwe'relisteningon
Serviceservice;//Theservicetoprovideonthatport
volatilebooleanstop=false;//Whetherwe'vebeenaskedtostop
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*TheListenerconstructorcreatesathreadforitselfinthe
*threadgroup.ItcreatesaServerSockettolistenforconnections
*onthespecifiedport.ItarrangesfortheServerSockettobe
*interruptible,sothatservicescanberemovedfromtheserver.
**/
publicListener(ThreadGroupgroup,intport,Serviceservice)
throwsIOException
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
super(group,"Listener:"+port);
listen_socket=newServerSocket(port);
//giveitanon-zerotimeoutsoaccept()canbeinterrupted
listen_socket.setSoTimeout(5000);
this.port=port;
this.service=service;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisisthepolitewaytogetaListenertostopaccepting
*connections
***/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidpleaseStop()...{
this.stop=true;//Setthestopflag
this.interrupt();//Stopblockinginaccept()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{listen_socket.close();}//Stoplistening.
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(IOExceptione)...{}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*AListenerisaThread,andthisisitsbody.
*Waitforconnectionrequests,acceptthem,andpassthesocketon
*totheaddConnectionmethodoftheserver.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidrun()...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(!stop)...{//loopuntilwe'reaskedtostop.
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
Socketclient=listen_socket.accept();
addConnection(client,service);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(InterruptedIOExceptione)...{}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(IOExceptione)...{log(e);}
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisisthemethodthatListenerobjectscallwhentheyaccepta
*connectionfromaclient.IteithercreatesaConnectionobject
*fortheconnectionandaddsittothelistofcurrentconnections,
*or,ifthelimitonconnectionshasbeenreached,itclosesthe
*connection.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
protectedsynchronizedvoidaddConnection(Sockets,Serviceservice)...{
//Iftheconnectionlimithasbeenreached
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(connections.size()>=maxConnections)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
//Thentelltheclientitisbeingrejected.
PrintWriterout=newPrintWriter(s.getOutputStream());
out.print("Connectionrefused;"+
"theserverisbusy;pleasetryagainlater. ");
out.flush();
//Andclosetheconnectiontotherejectedclient.
s.close();
//Andlogit,ofcourse
log("Connectionrefusedto"+
s.getInetAddress().getHostAddress()+
":"+s.getPort()+":maxconnectionsreached.");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
}catch(IOExceptione)...{log(e);}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{//Otherwise,ifthelimithasnotbeenreached
//CreateaConnectionthreadtohandlethisconnection
Connectionc=newConnection(s,service);
//Addittothelistofcurrentconnections
connections.add(c);
//Logthisnewconnection
log("Connectedto"+s.getInetAddress().getHostAddress()+
":"+s.getPort()+"onport"+s.getLocalPort()+
"forservice"+service.getClass().getName());
//AndstarttheConnectionthreadtoprovidetheservice
c.start();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*AConnectionthreadcallsthismethodjustbeforeitexits.Itremoves
*thespecifiedConnectionfromthesetofconnections.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
protectedsynchronizedvoidendConnection(Connectionc)...{
connections.remove(c);
log("Connectionto"+c.client.getInetAddress().getHostAddress()+
":"+c.client.getPort()+"closed.");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**Changethecurrentconnectionlimit*/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedvoidsetMaxConnections(intmax)...{
maxConnections=max;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thismethoddisplaysstatusinformationabouttheserveronthe
*specifiedstream.Itcanbeusedfordebugging,andisusedbythe
*Controlservicelaterinthisexample.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedvoiddisplayStatus(PrintWriterout)...{
//DisplayalistofallServicesthatarebeingprovided
Iteratorkeys=services.keySet().iterator();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(keys.hasNext())...{
Integerport=(Integer)keys.next();
Listenerlistener=(Listener)services.get(port);
out.print("SERVICE"+listener.service.getClass().getName()
+"ONPORT"+port+" ");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Displaythecurrentconnectionlimit
out.print("MAXCONNECTIONS:"+maxConnections+" ");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Displayalistofallcurrentconnections
Iteratorconns=connections.iterator();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(conns.hasNext())...{
Connectionc=(Connection)conns.next();
out.print("CONNECTEDTO"+
c.client.getInetAddress().getHostAddress()+
":"+c.client.getPort()+"ONPORT"+
c.client.getLocalPort()+"FORSERVICE"+
c.service.getClass().getName()+" ");
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisclassisasubclassofThreadthathandlesanindividual
*connectionbetweenaclientandaServiceprovidedbythisserver.
*Becauseeachsuchconnectionhasathreadofitsown,eachServicecan
*havemultipleconnectionspendingatonce.Despitealltheother
*threadsinuse,thisisthekeyfeaturethatmakesthisa
*multi-threadedserverimplementation.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicclassConnectionextendsThread...{
Socketclient;//Thesockettotalktotheclientthrough
Serviceservice;//Theservicebeingprovidedtothatclient
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisconstructorjustsavessomestateandcallsthesuperclass
*constructortocreateathreadtohandletheconnection.Connection
*objectsarecreatedbyListenerthreads.Thesethreadsarepartof
*theserver'sThreadGroup,soallConnectionthreadsarepartofthat
*group,too.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicConnection(Socketclient,Serviceservice)...{
super("Server.Connection:"+
client.getInetAddress().getHostAddress()+
":"+client.getPort());
this.client=client;
this.service=service;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisisthebodyofeachandeveryConnectionthread.
*Allitdoesispasstheclientinputandoutputstreamstothe
*serve()methodofthespecifiedServiceobject.Thatmethodis
*responsibleforreadingfromandwritingtothosestreamsto
*providetheactualservice.RecallthattheServiceobjecthas
*beenpassedfromtheServer.addService()methodtoaListener
*objecttotheaddConnection()methodtothisConnectionobject,and
*isnowfinallybeingusedtoprovidetheservice.Notethatjust
*beforethisthreadexitsitalwayscallstheendConnection()method
*toremoveitselffromthesetofconnections
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidrun()...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
InputStreamin=client.getInputStream();
OutputStreamout=client.getOutputStream();
service.serve(in,out);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(IOExceptione)...{log(e);}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
finally...{endConnection(this);}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*HereistheServiceinterfacethatwehaveseensomuchof.Itdefines
*onlyasinglemethodwhichisinvokedtoprovidetheservice.serve()
*willbepassedaninputstreamandanoutputstreamtotheclient.It
*shoulddowhateveritwantswiththem,andshouldclosethembefore
*returning.
*
*Allconnectionsthroughthesameporttothisserviceshareasingle
*Serviceobject.Thus,anystatelocaltoanindividualconnectionmust
*bestoredinlocalvariableswithintheserve()method.Statethat
*shouldbeglobaltoallconnectionsonthesameportshouldbestored
*ininstancevariablesoftheServiceclass.IfthesameServiceis
*runningonmorethanoneport,therewilltypicallybedifferent
*Serviceinstancesforeachport.Datathatshouldbeglobaltoall
*connectionsonanyportshouldbestoredinstaticvariables.
*
*Notethatimplementationsofthisinterfacemusthaveano-argument
*constructoriftheyaretobedynamicallyinstantiatedbythemain()
*methodoftheServerclass.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicinterfaceService...{
publicvoidserve(InputStreamin,OutputStreamout)throwsIOException;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Averysimpleservice.Itdisplaysthecurrenttimeontheserver
*totheclient,andclosestheconnection.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticclassTimeimplementsService...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidserve(InputStreami,OutputStreamo)throwsIOException...{
PrintWriterout=newPrintWriter(o);
out.print(newDate()+" ");
out.close();
i.close();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisisanotherexampleservice.Itreadslinesofinputfromthe
*client,andsendsthemback,reversed.Italsodisplaysawelcome
*messageandinstructions,andclosestheconnectionwhentheuser
*entersa'.'onalinebyitself.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticclassReverseimplementsService...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidserve(InputStreami,OutputStreamo)throwsIOException...{
BufferedReaderin=newBufferedReader(newInputStreamReader(i));
PrintWriterout=
newPrintWriter(newBufferedWriter(newOutputStreamWriter(o)));
out.print("Welcometothelinereversalserver. ");
out.print("Enterlines.Endwitha'.'onalinebyitself. ");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(;;)...{
out.print(">");
out.flush();
Stringline=in.readLine();
if((line==null)||line.equals("."))break;
for(intj=line.length()-1;j>=0;j--)
out.print(line.charAt(j));
out.print(" ");
}
out.close();
in.close();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*ThisserviceisanHTTPmirror,justliketheHttpMirrorclass
*implementedearlierinthischapter.Itechosbacktheclient's
*HTTPrequest
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticclassHTTPMirrorimplementsService...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidserve(InputStreami,OutputStreamo)throwsIOException...{
BufferedReaderin=newBufferedReader(newInputStreamReader(i));
PrintWriterout=newPrintWriter(o);
out.print("HTTP/1.0200 ");
out.print("Content-Type:text/plain ");
Stringline;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while((line=in.readLine())!=null)...{
if(line.length()==0)break;
out.print(line+" ");
}
out.close();
in.close();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisservicedemonstrateshowtomaintainstateacrossconnectionsby
*savingitininstancevariablesandusingsynchronizedaccesstothose
*variables.Itmaintainsacountofhowmanyclientshaveconnectedand
*tellseachclientwhatnumberitis
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticclassUniqueIDimplementsService...{
publicintid=0;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicsynchronizedintnextId()...{returnid++;}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidserve(InputStreami,OutputStreamo)throwsIOException...{
PrintWriterout=newPrintWriter(o);
out.print("Youareclient#:"+nextId()+" ");
out.close();
i.close();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisisanon-trivialservice.Itimplementsacommand-basedprotocol
*thatgivespassword-protectedruntimecontrolovertheoperationofthe
*server.Seethemain()methodoftheServerclasstoseehowthis
*serviceisstarted.
*
*Therecognizedcommandsare:
*password:givepassword;authorizationisrequiredformostcommands
*add:dynamicallyaddanamedserviceonaspecifiedport
*remove:dynamicallyremovetheservicerunningonaspecifiedport
*max:changethecurrentmaximumconnectionlimit.
*status:displaycurrentservices,connections,andconnectionlimit
*help:displayahelpmessage
*quit:disconnect
*
*Thisservicedisplaysaprompt,andsendsallofitsoutputtotheuser
*incapitalletters.Onlyoneclientisallowedtoconnecttothis
*serviceatatime.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicstaticclassControlimplementsService...{
Serverserver;//Theserverwecontrol
Stringpassword;//Thepasswordwerequire
booleanconnected=false;//Whetheraclientisalreadyconnected
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*CreateanewControlservice.ItwillcontrolthespecifiedServer
*object,andwillrequirethespecifiedpasswordforauthorization
*NotethatthisServicedoesnothaveanoargumentconstructor,
*whichmeansthatitcannotbedynamicallyinstantiatedandaddedas
*theother,genericservicesabovecanbe.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicControl(Serverserver,Stringpassword)...{
this.server=server;
this.password=password;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/***//**
*Thisistheservemethodthatprovidestheservice.Itreadsa
*linetheclient,andusesjava.util.StringTokenizertoparseit
*intocommandsandarguments.Itdoesvariousthingsdependingon
*thecommand.
**/
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
publicvoidserve(InputStreami,OutputStreamo)throwsIOException...{
//Setupthestreams
BufferedReaderin=newBufferedReader(newInputStreamReader(i));
PrintWriterout=newPrintWriter(o);
Stringline;//Forreadingclientinputlines
//Hastheuserhasgiventhepasswordyet?
booleanauthorized=false;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Ifthereisalreadyaclientconnectedtothisservice,display
//amessagetothisclientandclosetheconnection.Weusea
//synchronizedblocktopreventaracecondition.
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
synchronized(this)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(connected)...{
out.print("ONLYONECONTROLCONNECTIONALLOWED. ");
out.close();
return;
}
elseconnected=true;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//Thisisthemainloop:readacommand,parseit,andhandleit
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(;;)...{//infiniteloop
out.print(">");//Displayaprompt
out.flush();//Makeitappearrightaway
line=in.readLine();//Gettheuser'sinput
if(line==null)break;//QuitifwegetEOF.
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
//UseaStringTokenizertoparsetheuser'scommand
StringTokenizert=newStringTokenizer(line);
if(!t.hasMoreTokens())continue;//ifinputwasempty
//Getfirstwordoftheinputandconverttolowercase
Stringcommand=t.nextToken().toLowerCase();
//Nowcomparetoeachofthepossiblecommands,doingthe
//appropriatethingforeachcommand
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(command.equals("password"))...{//Passwordcommand
Stringp=t.nextToken();//Getthenextword
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(p.equals(this.password))...{//Isitthepassword?
out.print("OK ");//Sayso
authorized=true;//Grantauthorization
}
elseout.print("INVALIDPASSWORD ");
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
elseif(command.equals("add"))...{//AddServicecommand
//Checkwhetherpasswordhasbeengiven
if(!authorized)out.print("PASSWORDREQUIRED ");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{
//Getthenameoftheserviceandtryto
//dynamicallyloadandinstantiateit.
//Exceptionswillbehandledbelow
StringserviceName=t.nextToken();
ClassserviceClass=Class.forName(serviceName);
Serviceservice;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
service=(Service)serviceClass.newInstance();
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(NoSuchMethodErrore)...{
thrownewIllegalArgumentException(
"Servicemusthavea"+
"no-argumentconstructor");
}
intport=Integer.parseInt(t.nextToken());
//Ifnoexceptionsoccurred,addtheservice
server.addService(service,port);
out.print("SERVICEADDED ");//acknowledge
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
elseif(command.equals("remove"))...{//Removeservice
if(!authorized)out.print("PASSWORDREQUIRED ");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{
intport=Integer.parseInt(t.nextToken());
server.removeService(port);//removetheservice
out.print("SERVICEREMOVED ");//acknowledge
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
elseif(command.equals("max"))...{//Setconnectionlimit
if(!authorized)out.print("PASSWORDREQUIRED ");
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{
intmax=Integer.parseInt(t.nextToken());
server.setMaxConnections(max);
out.print("MAXCONNECTIONSCHANGED ");
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
elseif(command.equals("status"))...{//StatusDisplay
if(!authorized)out.print("PASSWORDREQUIRED ");
elseserver.displayStatus(out);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
elseif(command.equals("help"))...{//Helpcommand
//Displaycommandsyntax.Passwordnotrequired
out.print("COMMANDS: "+
" password<password> "+
" add<service><port> "+
" remove<port> "+
" max<max-connections> "+
" status "+
" help "+
" quit ");
}
elseif(command.equals("quit"))break;//Quitcommand.
elseout.print("UNRECOGNIZEDCOMMAND ");//Error
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch(Exceptione)...{
//Ifanexceptionoccurredduringthecommand,printan
//errormessage,thenoutputdetailsoftheexception.
out.print("ERRORWHILEPARSINGOREXECUTINGCOMMAND: "+
e+" ");
}
}
//Finally,whentheloopcommandloopends,closethestreams
//andsetourconnectedflagtofalsesothatotherclientscan
//nowconnect.
connected=false;
out.close();
in.close();
}
}
}