import java.net.*;
import java.io.*;
/** A multithreaded variation of EchoServer.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* .
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class ThreadedEchoServer extends EchoServer
implements Runnable {
public static void main(String[] args) {
int port = 8088;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {}
}
ThreadedEchoServer echoServer =
new ThreadedEchoServer(port, 0);
echoServer.serverName = "Threaded EchoServer";
}
public ThreadedEchoServer(int port, int connections) {
super(port, connections);
}
/** The new version of handleConnection starts a thread. This
* new thread will call back to the old version of
* handleConnection, resulting in the same server behavior
* in a multithreaded version. The thread stores the Socket
* instance since run doesn't take any arguments, and since
* storing the socket in an instance variable risks having
* it overwritten if the next thread starts before the run
* method gets a chance to copy the socket reference.
*/
public void handleConnection(Socket server) {
Connection connectionThread = new Connection(this, server);
connectionThread.start();
}
public void run() {
Connection currentThread =
(Connection)Thread.currentThread();
try {
super.handleConnection(currentThread.getSocket());
} catch(IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
}
}
}
/** This is just a Thread with a field to store a Socket object.
* Used as a thread-safe means to pass the Socket from
* handleConnection to run.
*/
class Connection extends Thread {
private Socket serverSocket;
public Connection(Runnable serverObject,
Socket serverSocket) {
super(serverObject);
this.serverSocket = serverSocket;
}
public Socket getSocket() {
return serverSocket;
}
}
EchoServer.java Creates a Web page showing all data sent from the client (browser).
import java.net.*;
import java.io.*;
import java.util.StringTokenizer;
/** A simple HTTP server that generates a Web page showing all
* of the data that it received from the Web client (usually
* a browser). To use this server, start it on the system of
* your choice, supplying a port number if you want something
* other than port 8088. Call this system server.com. Next,
* start a Web browser on the same or a different system, and
* connect to http://server.com:8088/whatever. The resultant
* Web page will show the data that your browser sent. For
* debugging in servlet or CGI programming, specify
* http://server.com:8088/whatever as the ACTION of your HTML
* form. You can send GET or POST data; either way, the
* resultant page will show what your browser sent.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class EchoServer extends NetworkServer {
protected int maxRequestLines = 50;
protected String serverName = "EchoServer";
/** Supply a port number as a command-line
* argument. Otherwise, use port 8088.
*/
public static void main(String[] args) {
int port = 8088;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {}
}
new EchoServer(port, 0);
}
public EchoServer(int port, int maxConnections) {
super(port, maxConnections);
listen();
}
/** Overrides the NetworkServer handleConnection method to
* read each line of data received, save it into an array
* of strings, then send it back embedded inside a PRE
* element in an HTML page.
*/
public void handleConnection(Socket server)
throws IOException{
System.out.println
(serverName + ": got connection from " +
server.getInetAddress().getHostName());
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
String[] inputLines = new String[maxRequestLines];
int i;
for (i=0; i\n" +
"\n" +
"\n" +
" \n" +
"\n" +
"\n" +
"\n" +
"
" + serverName +
" Results
\n" +
"Here is the request line and request headers\n" +
"sent by your browser:\n" +
"
");
}
// Print bottom of a standard Web page.
private void printTrailer(PrintWriter out) {
out.println
("
\n" +
"\n" +
"\n");
}
// Normal Web page requests use GET, so this server can simply
// read a line at a time. However, HTML forms can also use
// POST, in which case we have to determine the number of POST
// bytes that are sent so we know how much extra data to read
// after the standard HTTP headers.
private boolean usingPost(String[] inputs) {
return(inputs[0].toUpperCase().startsWith("POST"));
}
private void readPostData(String[] inputs, int i,
BufferedReader in)
throws IOException {
int contentLength = contentLength(inputs);
char[] postData = new char[contentLength];
in.read(postData, 0, contentLength);
inputs[++i] = new String(postData, 0, contentLength);
}
// Given a line that starts with Content-Length,
// this returns the integer value specified.
private int contentLength(String[] inputs) {
String input;
for (int i=0; iOverride this method in servers
* you write.
*
* This generic version simply reports the host that made
* the connection, shows the first line the client sent,
* and sends a single line in response.
*/
protected void handleConnection(Socket server)
throws IOException{
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
System.out.println
("Generic Network Server: got connection from " +
server.getInetAddress().getHostName() + "\n" +
"with first line '" + in.readLine() + "'");
out.println("Generic Network Server");
server.close();
}
/** Gets the max connections server will handle before
* exiting. A value of 0 indicates that server should run
* until explicitly killed.
*/
public int getMaxConnections() {
return(maxConnections);
}
/** Sets max connections. A value of 0 indicates that server
* should run indefinitely (until explicitly killed).
*/
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/** Gets port on which server is listening. */
public int getPort() {
return(port);
}
/** Sets port. You can only do before "connect" is
* called. That usually happens in the constructor.
*/
protected void setPort(int port) {
this.port = port;
}
}
SocketUtil.java Simplifies the creation of a PrintWriter and BufferedReader.
import java.net.*;
import java.io.*;
/** A shorthand way to create BufferedReaders and
* PrintWriters associated with a Socket.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class SocketUtil {
/** Make a BufferedReader to get incoming data. */
public static BufferedReader getReader(Socket s)
throws IOException {
return(new BufferedReader(
new InputStreamReader(s.getInputStream())));
}
/** Make a PrintWriter to send outgoing data.
* This PrintWriter will automatically flush stream
* when println is called.
*/
public static PrintWriter getWriter(Socket s)
throws IOException {
// Second argument of true means autoflush.
return(new PrintWriter(s.getOutputStream(), true));
}
}
Similar Posts