1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright (C) 1998 by Jason Hunter <jhunter@acm.org>. All rights reserved.
// Use of this class is limited. Please see the LICENSE for more information.
package maj;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* A superclass for HTTP servlets that wish to accept raw socket
* connections. DaemonHttpServlet
* starts listening for client requests in its <tt>init()</tt> method
* and stops listening in its <tt>destroy()</tt> method. In between,
* for every connection it receives, it calls the abstract
* <tt>handleClient(Socket client)</tt> method. This method should
* be implemented by the servlet subclassing DaemonHttpServlet.
* The port on which the servlet is to listen is determined by the
* <tt>getSocketPort()</tt> method.
*
* @see com.oreilly.servlet.RemoteDaemonHttpServlet
*
* @author <b>Jason Hunter</b>, Copyright © 1998
* @version 1.0, 98/09/18
*/
public abstract class DaemonHttpServlet extends HttpServlet {
/**
* The default listening port (1313)
*/
protected int DEFAULT_PORT = 1313;
private Thread daemonThread;
/**
* Begins a thread listening for socket connections. Subclasses
* that override this method must be sure to first call
* <tt>super.init(config)</tt>.
*
* @param config the servlet config
* @exception ServletException if a servlet exception occurs
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
daemonThread = new Daemon(this);
daemonThread.start();
}
catch (Exception e) {
log("Problem starting socket server daemon thread" +
e.getClass().getName() + ": " + e.getMessage());
}
}
/**
* Returns the socket port on which the servlet will listen.
* A servlet can change the port in three ways: by using the
* <tt>socketPort</tt> init parameter, by setting the <tt>DEFAULT_PORT</tt>
* variable before calling <tt>super.init()</tt>, or by overriding this
* method's implementation.
*
* @return the port number on which to listen
*/
protected int getSocketPort() {
try { return Integer.parseInt(getInitParameter("socketPort")); }
catch (NumberFormatException e) { return DEFAULT_PORT; }
}
/**
* Handles a new socket connection. Subclasses must define this method.
*
* @param client the client socket
*/
abstract public void handleClient(Socket client);
/**
* Halts the thread listening for socket connections. Subclasses
* that override this method must be sure to first call
* <tt>super.destroy()</tt>.
*/
@Override
public void destroy() {
try {
daemonThread.stop();
daemonThread = null;
}
catch (Exception e) {
log("Problem stopping server socket daemon thread: " +
e.getClass().getName() + ": " + e.getMessage());
}
}
}
// This work is broken into a helper class so that subclasses of
// DaemonHttpServlet can define their own run() method without problems.
class Daemon extends Thread {
private ServerSocket serverSocket;
private DaemonHttpServlet servlet;
public Daemon(DaemonHttpServlet servlet) {
this.servlet = servlet;
}
@Override
public void run() {
try {
// Create a server socket to accept connections
serverSocket = new ServerSocket(servlet.getSocketPort());
}
catch (Exception e) {
servlet.log("Problem establishing server socket: " +
e.getClass().getName() + ": " + e.getMessage());
return;
}
try {
while (true) {
// As each connection comes in, call the servlet's handleClient().
// Note this method is blocking. It's the servlet's responsibility
// to spawn a handler thread for long-running connections.
try {
servlet.handleClient(serverSocket.accept());
}
catch (IOException ioe) {
servlet.log("Problem accepting client's socket connection: " +
ioe.getClass().getName() + ": " + ioe.getMessage());
}
}
}
catch (ThreadDeath e) {
// When the thread is killed, close the server socket
try {
serverSocket.close();
}
catch (IOException ioe) {
servlet.log("Problem closing server socket: " +
ioe.getClass().getName() + ": " + ioe.getMessage());
}
}
}
} |
Partager