Java安全机制其实有点不安全

看下面的这段代码,摘自《Java Examples in a Nutsbell》(java实例技术手册):

就是一个简单的通用的多线程服务器

这个例子可以通过配置参数:

1
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 "
:10
24-4444”,“listen”;就可以了。端口该闭的就闭了。如果用accept和connect反而没有什么用。不知道java的安全性高在什么地方。因为j
ava.policy文件中从1024以上的端口全都使用了listen。所以以后要配置端口时一定要注意。

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) // /*

* Copyright © 2004 David Flanagan.  All rights reserved.

* This code is from the book Java Examples in a Nutshell, 3nd Edition.

* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.

* You may study, use, and modify it for any non-commercial purpose,

* including teaching and use in open-source projects.

* You may distribute it non-commercially as long as you retain this notice.

* For a commercial use license, or to purchase the book,

* please visit http://www.davidflanagan.com/javaexamples3.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) /

package je3.net;

import java.io. * ;

import java.net. * ;

import java.util. * ;

import java.util.logging. * ;

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) /
 / /


* This class is a generic framework for a flexible, multi-threaded server.

* It listens on any number of specified ports, and, when it receives a

* connection on a port, passes input and output streams to a specified Service

* object which provides the actual service.  It can limit the number of

* concurrent connections, and logs activity to a specified stream.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) public class Server … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A main() method for running the server as a standalone program.  The

* command-line arguments to the program should be pairs of servicenames

* and port numbers.  For each pair, the program will dynamically load the

* named Service class, instantiate it, and tell the server to provide

* that Service on the specified port.  The special -control argument

* should be followed by a password and port, and will start special

* server control service running on the specified port, protected by the

* specified password.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static void main(String[] args) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

if (args.length < 2 ) // Check number of arguments

throw new IllegalArgumentException( " Must specify a service " );


// Create a server object that has a limit of 10 concurrent

// connections, and logs to a Logger at the Level.INFO level

// Prior to Java 1.4 we did this: new Server(System.out, 10);

Server s = new Server(Logger.getLogger(Server. class .getName()),

Level.INFO, 10 );


// Parse the argument list

int i = 0 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (i < args.length) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (args[i].equals( " -control " )) … {
// Handle the -control arg

i ++ ;

String password = args[i ++ ];

int port = Integer.parseInt(args[i ++ ]);

// add control service

s.addService( new Control(s, password), port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

// Otherwise start a named service on the specified port.

// Dynamically load and instantiate a Service class

String serviceName = args[i ++ ];

Class serviceClass = Class.forName(serviceName);

Service service = (Service)serviceClass.newInstance();

int port = Integer.parseInt(args[i ++ ]);

s.addService(service, port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (Exception e) … { // Display a message
if anything goes wrong

System.err.println( " Server: " + e);

System.err.println( " Usage: java Server " +

" [-control  ] " +

" [  … ] " );

System.exit( 1 );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// This is the state for the server

Map services; // Hashtable mapping ports to Listeners

Set connections; // The set of current connections

int maxConnections; // The concurrent connection limit

ThreadGroup threadGroup; // The threadgroup for all our threads


// This class was originally written to send logging output to a stream.

// It has been retrofitted to also support the java.util.logging API of

// Java 1.4.  You can use either, neither, or both.

PrintWriter logStream; // Where we send our logging output to

Logger logger; // A Java 1.4 logging destination

Level logLevel; // the level to log messages at

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the Server() constructor.  It must be passed a stream

* to send log output to (may be null), and the limit on the number of

* concurrent connections.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server(OutputStream logStream, int
maxConnections) … {

this (maxConnections);

setLogStream(logStream);

log( " Starting server " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor added to support logging with the Java 1.4 Logger class
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server(Logger logger, Level logLevel, int
maxConnections) … {

this (maxConnections);

setLogger(logger, logLevel);

log( " Starting server " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor supports no logging
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Server( int maxConnections) … {

threadGroup = new ThreadGroup(Server. class .getName());

this .maxConnections = maxConnections;

services = new HashMap();

connections = new HashSet(maxConnections);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A public method to set the current logging stream.  Pass null

* to turn logging off.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void
setLogStream(OutputStream out) … {

if (out != null ) logStream = new PrintWriter(out);

else logStream = null ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Set the current Logger and logging level. Pass null to turn logging off.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void setLogger(Logger
logger, Level level) … {

this .logger = logger;

this .logLevel = level;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Write the specified string to the log
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void log(String s) …
{

if (logger != null ) logger.log(logLevel, s);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (logStream != null ) … {

logStream.println( " [ " + new Date() + " ] " + s);

logStream.flush();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Write the specified object to the log
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected void log(Object o) … {
log(o.toString()); }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method makes the server start providing a new service.

* It runs the specified Service object on the specified port.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /

public synchronized void addService(Service service, int port)

throws IOException
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

Integer key = new Integer(port); // the hashtable key

// Check whether a service is already on that port

if (services.get(key) != null )

throw new IllegalArgumentException( " Port " + port +

" already in use. " );

// Create a Listener object to listen for connections on the port

Listener listener = new Listener(threadGroup, port, service);

// Store it in the hashtable

services.put(key, listener);

// Log it

log( " Starting service " + service.getClass().getName() +

" on port " + port);

// Start the listener running.

listener.start();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method makes the server stop providing a service on a port.

* It does not terminate any pending connections to that service, merely

* causes the server to stop accepting new connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void removeService( int
port) … {

Integer key = new Integer(port); // hashtable key

// Look up the Listener object for the port in the hashtable

final Listener listener = (Listener) services.get(key);

if (listener == null ) return ;

// Ask the listener to stop

listener.pleaseStop();

// Remove it from the hashtable

services.remove(key);

// And log it.

log( " Stopping service " + listener.service.getClass().getName() +

" on port " + port);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This nested Thread subclass is a “listener”.  It listens for

* connections on a specified port (using a ServerSocket) and when it gets

* a connection request, it calls the servers addConnection() method to

* accept (or reject) the connection.  There is one Listener for each

* Service being provided by the Server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public class Listener extends Thread … {

ServerSocket listen_socket; // The socket to listen for connections

int port; // The port we’re listening on

Service service; // The service to provide on that port

volatile boolean stop = false ; // Whether we’ve been asked to stop

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* The Listener constructor creates a thread for itself in the

* threadgroup.  It creates a ServerSocket to listen for connections

* on the specified port.  It arranges for the ServerSocket to be

* interruptible, so that services can be removed from the server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /

public Listener(ThreadGroup group, int port, Service service)

throws IOException
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

super (group, " Listener: " + port);

listen_socket = new ServerSocket(port);

// give it a non-zero timeout so accept() can be interrupted

listen_socket.setSoTimeout( 5000 );

this .port = port;

this .service = service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the polite way to get a Listener to stop accepting

* connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) ** /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void pleaseStop() … {

this .stop = true ; // Set the stop flag

this .interrupt(); // Stop blocking in accept()
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … { listen_socket.close(); } // Stop
listening.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A Listener is a Thread, and this is its body.

* Wait for connection requests, accept them, and pass the socket on

* to the addConnection method of the server.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void run() … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while ( ! stop) … { // loop until we’re
asked to stop.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

Socket client = listen_socket.accept();

addConnection(client, service);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (InterruptedIOException e) … {}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the method that Listener objects call when they accept a

* connection from a client.  It either creates a Connection object

* for the connection and adds it to the list of current connections,

* or, if the limit on connections has been reached, it closes the

* connection.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void addConnection(Socket
s, Service service) … {

// If the connection limit has been reached
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (connections.size() >= maxConnections) …
{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

// Then tell the client it is being rejected.

PrintWriter out = new PrintWriter(s.getOutputStream());

out.print( " Connection refused; " +

" the server is busy; please try again later. " );

out.flush();

// And close the connection to the rejected client.

s.close();

// And log it, of course

log( " Connection refused to " +

s.getInetAddress().getHostAddress() +

" : " + s.getPort() + " : max connections reached. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) } catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … { // Otherwise, if the limit has not
been reached

// Create a Connection thread to handle this connection

Connection c = new Connection(s, service);

// Add it to the list of current connections

connections.add©;

// Log this new connection

log( " Connected to " + s.getInetAddress().getHostAddress() +

" : " + s.getPort() + " on port " + s.getLocalPort() +

" for service " + service.getClass().getName());

// And start the Connection thread to provide the service

c.start();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A Connection thread calls this method just before it exits.  It removes

* the specified Connection from the set of connections.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) protected synchronized void
endConnection(Connection c) … {

connections.remove©;

log( " Connection to " + c.client.getInetAddress().getHostAddress() +

" : " + c.client.getPort() + " closed. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /* Change the current connection limit
/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void setMaxConnections( int
max) … {

maxConnections = max;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This method displays status information about the server on the

* specified stream.  It can be used for debugging, and is used by the

* Control service later in this example.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized void
displayStatus(PrintWriter out) … {

// Display a list of all Services that are being provided

Iterator keys = services.keySet().iterator();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (keys.hasNext()) … {

Integer port = (Integer) keys.next();

Listener listener = (Listener) services.get(port);

out.print( " SERVICE " + listener.service.getClass().getName()

+ " ON PORT " + port + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// Display the current connection limit

out.print( " MAX CONNECTIONS: " + maxConnections + " " );


// Display a list of all current connections

Iterator conns = connections.iterator();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while (conns.hasNext()) … {

Connection c = (Connection)conns.next();

out.print( " CONNECTED TO " +

c.client.getInetAddress().getHostAddress() +

" : " + c.client.getPort() + " ON PORT " +

c.client.getLocalPort() + " FOR SERVICE " +

c.service.getClass().getName() + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This class is a subclass of Thread that handles an individual

* connection between a client and a Service provided by this server.

* Because each such connection has a thread of its own, each Service can

* have multiple connections pending at once.  Despite all the other

* threads in use, this is the key feature that makes this a

* multi-threaded server implementation.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public class Connection extends Thread … {

Socket client; // The socket to talk to the client through

Service service; // The service being provided to that client

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This constructor just saves some state and calls the superclass

* constructor to create a thread to handle the connection.  Connection

* objects are created by Listener threads.  These threads are part of

* the server’s ThreadGroup, so all Connection threads are part of that

* group, too.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Connection(Socket client, Service service)
… {

super ( " Server.Connection: " +

client.getInetAddress().getHostAddress() +

" : " + client.getPort());

this .client = client;

this .service = service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the body of each and every Connection thread.

* All it does is pass the client input and output streams to the

* serve() method of the specified Service object.  That method is

* responsible for reading from and writing to those streams to

* provide the actual service.  Recall that the Service object has

* been passed from the Server.addService() method to a Listener

* object to the addConnection() method to this Connection object, and

* is now finally being used to provide the service.  Note that just

* before this thread exits it always calls the endConnection() method

* to remove itself from the set of connections
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void run() … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

InputStream in = client.getInputStream();

OutputStream out = client.getOutputStream();

service.serve(in, out);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (IOException e) … {log(e);}
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) finally … { endConnection( this ); }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Here is the Service interface that we have seen so much of.  It defines

* only a single method which is invoked to provide the service.  serve()

* will be passed an input stream and an output stream to the client.  It

* should do whatever it wants with them, and should close them before

* returning.

*

* All connections through the same port to this service share a single

* Service object.  Thus, any state local to an individual connection must

* be stored in local variables within the serve() method.  State that

* should be global to all connections on the same port should be stored

* in instance variables of the Service class.  If the same Service is

* running on more than one port, there will typically be different

* Service instances for each port.  Data that should be global to all

* connections on any port should be stored in static variables.

*

* Note that implementations of this interface must have a no-argument

* constructor if they are to be dynamically instantiated by the main()

* method of the Server class.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public interface Service … {

public void serve(InputStream in, OutputStream out) throws IOException;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* A very simple service.  It displays the current time on the server

* to the client, and closes the connection.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Time implements Service
… {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

PrintWriter out = new PrintWriter(o);

out.print( new Date() + " " );

out.close();

i.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is another example service.  It reads lines of input from the

* client, and sends them back, reversed.  It also displays a welcome

* message and instructions, and closes the connection when the user

* enters a ‘.’ on a line by itself.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Reverse implements Service
… {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out =

new PrintWriter( new BufferedWriter( new OutputStreamWriter(o)));

out.print( " Welcome to the line reversal server. " );

out.print( " Enter lines.  End with a ‘.’ on a line by itself. " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) for (;😉 … {

out.print( " > " );

out.flush();

String line = in.readLine();

if ((line == null ) || line.equals( " . " )) break ;

for ( int j = line.length() - 1 ; j >= 0 ; j -- )

out.print(line.charAt(j));

out.print( " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This service is an HTTP mirror, just like the HttpMirror class

* implemented earlier in this chapter.  It echos back the client’s

* HTTP request
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class HTTPMirror implements
Service … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out = new PrintWriter(o);

out.print( " HTTP/1.0 200 " );

out.print( " Content-Type: text/plain " );

String line;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) while ((line = in.readLine()) != null ) …
{

if (line.length() == 0 ) break ;

out.print(line + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This service demonstrates how to maintain state across connections by

* saving it in instance variables and using synchronized access to those

* variables.  It maintains a count of how many clients have connected and

* tells each client what number it is
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class UniqueID implements
Service … {

public int id = 0 ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public synchronized int nextId() … { return
id ++ ; }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

PrintWriter out = new PrintWriter(o);

out.print( " You are client #: " + nextId() + " " );

out.close();

i.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is a non-trivial service.  It implements a command-based protocol

* that gives password-protected runtime control over the operation of the

* server.  See the main() method of the Server class to see how this

* service is started.

*

* The recognized commands are:

*   password: give password; authorization is required for most commands

*   add:      dynamically add a named service on a specified port

*   remove:   dynamically remove the service running on a specified port

*   max:      change the current maximum connection limit.

*   status:   display current services, connections, and connection limit

*   help:     display a help message

*   quit:     disconnect

*

* This service displays a prompt, and sends all of its output to the user

* in capital letters.  Only one client is allowed to connect to this

* service at a time.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public static class Control implements Service
… {

Server server; // The server we control

String password; // The password we require

boolean connected = false ; // Whether a client is already connected

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* Create a new Control service.  It will control the specified Server

* object, and will require the specified password for authorization

* Note that this Service does not have a no argument constructor,

* which means that it cannot be dynamically instantiated and added as

* the other, generic services above can be.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * /
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public Control(Server server, String password)
… {

this .server = server;

this .password = password;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) /
/ /*

* This is the serve method that provides the service.  It reads a

* line the client, and uses java.util.StringTokenizer to parse it

* into commands and arguments.  It does various things depending on

* the command.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) * */
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) public void serve(InputStream i, OutputStream o)
throws IOException … {

// Setup the streams

BufferedReader in = new BufferedReader( new InputStreamReader(i));

PrintWriter out = new PrintWriter(o);

String line; // For reading client input lines

// Has the user has given the password yet?

boolean authorized = false ;


// If there is already a client connected to this service, display

// a message to this client and close the connection.  We use a

// synchronized block to prevent a race condition.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) synchronized ( this ) … {
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (connected) … {

out.print( " ONLY ONE CONTROL CONNECTION ALLOWED. " );

out.close();

return ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else connected = true ;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }


// This is the main loop: read a command, parse it, and handle it
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) for (;😉 … { // infinite loop

out.print( " > " ); // Display a prompt

out.flush(); // Make it appear right away

line = in.readLine(); // Get the user’s input

if (line == null ) break ; // Quit if we get EOF.
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

// Use a StringTokenizer to parse the user’s command

StringTokenizer t = new StringTokenizer(line);

if ( ! t.hasMoreTokens()) continue ; // if input was empty

// Get first word of the input and convert to lower case

String command = t.nextToken().toLowerCase();

// Now compare to each of the possible commands, doing the

// appropriate thing for each command
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (command.equals( " password " )) … {
// Password command

String p = t.nextToken(); // Get the next word
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) if (p.equals( this .password)) … { // Is
it the password?

out.print( " OK " ); // Say so

authorized = true ; // Grant authorization
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else out.print( " INVALID PASSWORD " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " add " )) … {
// Add Service command

// Check whether password has been given

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

// Get the name of the service and try to

// dynamically load and instantiate it.

// Exceptions will be handled below

String serviceName = t.nextToken();

Class serviceClass = Class.forName(serviceName);

Service service;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) try … {

service = (Service)serviceClass.newInstance();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (NoSuchMethodError e) … {

throw new IllegalArgumentException(

" Service must have a " +

" no-argument constructor " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

int port = Integer.parseInt(t.nextToken());

// If no exceptions occurred, add the service

server.addService(service, port);

out.print( " SERVICE ADDED " ); // acknowledge
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " remove " )) …
{ // Remove service

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

int port = Integer.parseInt(t.nextToken());

server.removeService(port); // remove the service

out.print( " SERVICE REMOVED " ); // acknowledge
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " max " )) … {
// Set connection limit

if ( ! authorized) out.print( " PASSWORD REQUIRED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else … {

int max = Integer.parseInt(t.nextToken());

server.setMaxConnections(max);

out.print( " MAX CONNECTIONS CHANGED " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " status " )) …
{ // Status Display

if ( ! authorized) out.print( " PASSWORD REQUIRED " );

else server.displayStatus(out);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) else if (command.equals( " help " )) … {
// Help command

// Display command syntax.  Password not required

out.print( " COMMANDS: " +

" password  " +

" add   " +

" remove  " +

" max  " +

" status " +

" help " +

" quit " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

else if (command.equals( " quit " )) break ; // Quit command.

else out.print( " UNRECOGNIZED COMMAND " ); // Error
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) catch (Exception e) … {

// If an exception occurred during the command, print an

// error message, then output details of the exception.

out.print( " ERROR WHILE PARSING OR EXECUTING COMMAND: " +

e + " " );
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }

// Finally, when the loop command loop ends, close the streams

// and set our connected flag to false so that other clients can

// now connect.

connected = false ;

out.close();

in.close();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockEnd.gif) }
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kEnd.gif) }