HttpWorker.java
资源名称:Source.rar [点击查看]
上传用户:songled
上传日期:2022-07-14
资源大小:94k
文件大小:7k
源码类别:
进程与线程
开发平台:
Java
- import java.io.*;
- import java.net.*;
- import java.util.*;
- // uses class ObjectFIFO from chapter 18
- public class HttpWorker extends Object {
- private static int nextWorkerID = 0;
- private File docRoot;
- private ObjectFIFO idleWorkers;
- private int workerID;
- private ObjectFIFO handoffBox;
- private Thread internalThread;
- private volatile boolean noStopRequested;
- public HttpWorker(
- File docRoot,
- int workerPriority,
- ObjectFIFO idleWorkers
- ) {
- this.docRoot = docRoot;
- this.idleWorkers = idleWorkers;
- workerID = getNextWorkerID();
- handoffBox = new ObjectFIFO(1); // only one slot
- // Just before returning, the thread should be
- // created and started.
- noStopRequested = true;
- Runnable r = new Runnable() {
- public void run() {
- try {
- runWork();
- } catch ( Exception x ) {
- // in case ANY exception slips through
- x.printStackTrace();
- }
- }
- };
- internalThread = new Thread(r);
- internalThread.setPriority(workerPriority);
- internalThread.start();
- }
- public static synchronized int getNextWorkerID() {
- // synchronized at the class level to ensure uniqueness
- int id = nextWorkerID;
- nextWorkerID++;
- return id;
- }
- public void processRequest(Socket s)
- throws InterruptedException {
- handoffBox.add(s);
- }
- private void runWork() {
- Socket s = null;
- InputStream in = null;
- OutputStream out = null;
- while ( noStopRequested ) {
- try {
- // Worker is ready to receive new service
- // requests, so it adds itself to the idle
- // worker queue.
- idleWorkers.add(this);
- // Wait here until the server puts a request
- // into the handoff box.
- s = (Socket) handoffBox.remove();
- in = s.getInputStream();
- out = s.getOutputStream();
- generateResponse(in, out);
- out.flush();
- } catch ( IOException iox ) {
- System.err.println(
- "I/O error while processing request, " +
- "ignoring and adding back to idle " +
- "queue - workerID=" + workerID);
- } catch ( InterruptedException x ) {
- // re-assert the interrupt
- Thread.currentThread().interrupt();
- } finally {
- // Try to close everything, ignoring
- // any IOExceptions that might occur.
- if ( in != null ) {
- try {
- in.close();
- } catch ( IOException iox ) {
- // ignore
- } finally {
- in = null;
- }
- }
- if ( out != null ) {
- try {
- out.close();
- } catch ( IOException iox ) {
- // ignore
- } finally {
- out = null;
- }
- }
- if ( s != null ) {
- try {
- s.close();
- } catch ( IOException iox ) {
- // ignore
- } finally {
- s = null;
- }
- }
- }
- }
- }
- private void generateResponse(
- InputStream in,
- OutputStream out
- ) throws IOException {
- BufferedReader reader =
- new BufferedReader(new InputStreamReader(in));
- String requestLine = reader.readLine();
- if ( ( requestLine == null ) ||
- ( requestLine.length() < 1 )
- ) {
- throw new IOException("could not read request");
- }
- System.out.println("workerID=" + workerID +
- ", requestLine=" + requestLine);
- StringTokenizer st = new StringTokenizer(requestLine);
- String filename = null;
- try {
- // request method, typically 'GET', but ignored
- st.nextToken();
- // the second token should be the filename
- filename = st.nextToken();
- } catch ( NoSuchElementException x ) {
- throw new IOException(
- "could not parse request line");
- }
- File requestedFile = generateFile(filename);
- BufferedOutputStream buffOut =
- new BufferedOutputStream(out);
- if ( requestedFile.exists() ) {
- System.out.println("workerID=" + workerID +
- ", 200 OK: " + filename);
- int fileLen = (int) requestedFile.length();
- BufferedInputStream fileIn =
- new BufferedInputStream(
- new FileInputStream(requestedFile));
- // Use this utility to make a guess obout the
- // content type based on the first few bytes
- // in the stream.
- String contentType =
- URLConnection.guessContentTypeFromStream(
- fileIn);
- byte[] headerBytes = createHeaderBytes(
- "HTTP/1.0 200 OK",
- fileLen,
- contentType
- );
- buffOut.write(headerBytes);
- byte[] buf = new byte[2048];
- int blockLen = 0;
- while ( ( blockLen = fileIn.read(buf) ) != -1 ) {
- buffOut.write(buf, 0, blockLen);
- }
- fileIn.close();
- } else {
- System.out.println("workerID=" + workerID +
- ", 404 Not Found: " + filename );
- byte[] headerBytes = createHeaderBytes(
- "HTTP/1.0 404 Not Found",
- -1,
- null
- );
- buffOut.write(headerBytes);
- }
- buffOut.flush();
- }
- private File generateFile(String filename) {
- File requestedFile = docRoot; // start at the base
- // Build up the path to the requested file in a
- // platform independent way. URL's use '/' in their
- // path, but this platform may not.
- StringTokenizer st = new StringTokenizer(filename, "/");
- while ( st.hasMoreTokens() ) {
- String tok = st.nextToken();
- if ( tok.equals("..") ) {
- // Silently ignore parts of path that might
- // lead out of the document root area.
- continue;
- }
- requestedFile =
- new File(requestedFile, tok);
- }
- if ( requestedFile.exists() &&
- requestedFile.isDirectory()
- ) {
- // If a directory was requested, modify the request
- // to look for the "index.html" file in that
- // directory.
- requestedFile =
- new File(requestedFile, "index.html");
- }
- return requestedFile;
- }
- private byte[] createHeaderBytes(
- String resp,
- int contentLen,
- String contentType
- ) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- BufferedWriter writer = new BufferedWriter(
- new OutputStreamWriter(baos));
- // Write the first line of the response, followed by
- // the RFC-specified line termination sequence.
- writer.write(resp + "rn");
- // If a length was specified, add it to the header
- if ( contentLen != -1 ) {
- writer.write(
- "Content-Length: " + contentLen + "rn");
- }
- // If a type was specified, add it to the header
- if ( contentType != null ) {
- writer.write(
- "Content-Type: " + contentType + "rn");
- }
- // A blank line is required after the header.
- writer.write("rn");
- writer.flush();
- byte[] data = baos.toByteArray();
- writer.close();
- return data;
- }
- public void stopRequest() {
- noStopRequested = false;
- internalThread.interrupt();
- }
- public boolean isAlive() {
- return internalThread.isAlive();
- }
- }