第六章:源代码
天下维客,你可以修改的网络知识库
[编辑]
样本库
在结束之前,先看一下完整的源代码,它包括了 EchoServer、mylib.Server 和 mylib.Reporter。
EchoServer
// $Id$
import java.io.*; import java.net.*; import mylib.*;
public class EchoServer extends Server {
public EchoServer( int port ) {
// The superclass knows what to do with the port number, we
// don't have to care about it
super( port );
}
// This is called by the Server class when a connection
// comes in. "in" and "out" come from the incoming socket
// connection
public void handleConnection( Socket socket ) {
try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
// just copy the input to the output
while (true)
out.write( in.read() );
} catch( IOException ie ) {
System.out.println( ie );
}
}
protected void cleanUp() {
System.out.println( "Cleaning up" );
}
static public void main( String args[] ) throws Exception {
// Grab the port number from the command-line
int port = Integer.parseInt( args[0] );
// Have debugging info sent to standard error stream Server.setDebugStream( System.err );
// Create the server, and it's up and running new EchoServer( port ); }
}
mylib.Server
// $Id$
package mylib;
import java.io.*; import java.net.*;
abstract public class Server implements Runnable {
// the port we'll be listening on private int port;
// how many connections we've handled int numConnections;
// the Reporter that's reporting on this Server private Reporter reporter;
// set this to true to tell the thread to stop accepting // connections private boolean mustQuit = false;
public Server( int port ) {
// remember the port number so the thread can
// listen on it
this.port = port;
// the constructor starts a background thread new Thread( this ).start();
// and start a reporter reporter = new Reporter( this ); }
// this is our background thread
public void run() {
ServerSocket ss = null;
try {
// get ready to listen
ss = new ServerSocket( port );
while (!mustQuit) {
// give out some debugging info
debug( "Listening on "+port );
// wait for an incoming connection
Socket s = ss.accept();
// record that we got another connection
numConnections++;
// more debugging info
debug( "Got connection on "+s );
// process the connection -- this is implemented
// by the subclass
handleConnection( s );
}
} catch( IOException ie ) {
debug( ie.toString() );
}
debug( "Shutting down "+ss );
cleanUp(); }
// the default implementation does nothing abstract public void handleConnection( Socket s );
// tell the thread to stop accepting connections
public void close() {
mustQuit = true;
reporter.close();
}
// Put any last-minute clean-up stuff in here
protected void cleanUp() {
}
// everything below provides a simple debug system for // this package
// set this to a print stream if you want debug info // sent to it; otherwise, leave it null static private PrintStream debugStream;
// we have two versions of this ...
static public void setDebugStream( PrintStream ps ) {
debugStream = ps;
}
// ... just for convenience
static public void setDebugStream( OutputStream out ) {
debugStream = new PrintStream( out );
}
// send debug info to the print stream, if there is one
static public void debug( String s ) {
if (debugStream!= null)
debugStream.println( s );
}
}
mylib.Reporter
// $Id$
package mylib;
class Reporter implements Runnable {
// the Server we are reporting on private Server server;
// our background thread private Thread thread;
// set this to true to tell the thread to stop accepting // connections private boolean mustQuit = false;
Reporter( Server server ) {
this.server = server;
// create a background thread thread = new Thread( this ); thread.start(); }
public void run() {
while (!mustQuit) {
// do the reporting
Server.debug( "server has had "+server.numConnections+" connections" );
// then pause a while
try {
Thread.sleep( 5000 );
} catch( InterruptedException ie ) {}
}
}
// tell the background thread to quit
public void close() {
mustQuit = true;
}
}


