⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serverthread.java

📁 纯java服务器
💻 JAVA
字号:
// $Id: ServerThread.java,v 1.42 2001/01/23 03:08:28 nconway Exp $
package tornado;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;

public class ServerThread extends Thread {
    private final static int READ_BLOCK = 8192;

    // per-client resources: these are recreated for every connection
    private Request request;
    private Response response;
    /** The file asked for by the client, if appropriate.*/
    private File requestFile;
    /** The message in the access log for this request.*/
    private CommonLogMessage accessLog;

    // per-server resources: these are created once per ServerThread
    private final ArrayList taskPool;
    private final ServerPool serverPool;

    /** Constructs a new ServerThread using the specified values. This should
      * only rarely be called directly: for most purposes, you should spawn
      * new threads using {@link tornado.ServerPool#addThread()}.
      */
    ServerThread(ThreadGroup group, ArrayList tPool, ServerPool sPool) {
        super(group, "");
        taskPool = tPool;
        serverPool = sPool;
    }

    /** Begins an infinite loop waiting for connections and serving them.*/
    public void run() {
        Socket socket;
        while (true) {
            synchronized (taskPool) {
                /* Wait until we find an incoming connection. If
                 * pool is non-empty, there is already a connection
                 * waiting to be processed, so we can skip the wait().*/
                while (taskPool.isEmpty()) {
                    try {
                        taskPool.wait();
                    } catch (InterruptedException e) {
                        /* We were interrupted by another thread. In the
                         * current design, this means the ServerPool wants
                         * us to die.*/
                        return;
                    }
                }
                // finally, we have an incoming connection
                socket = (Socket)taskPool.remove(0);
            }

            // start the HTTP transaction with the client
            try {
                request = new Request(socket);
                response = new Response(request);
                accessLog = new CommonLogMessage(request);
                handOffRequest();
            } catch (HTTPException e) {
                // we got a protocol error of some kind - expected
                sendErrorPage(e);
            } catch (Exception e) {
                // we got a more serious error - these should not occur
                e.printStackTrace();
            } finally {
                Tornado.log.logAccess(accessLog);
                finishConnection();
            }
        }
    }

    /** Decides what to do with a connection. This looks at the HTTP
      * headers sent by the client, sends error pages as necessary, and
      * then decides which method to use to actually handle this request.
      */
    private void handOffRequest() throws HTTPException {
        String method = request.getType();

        if (method == null) {
            return;
        } else if (method.equals("GET")) {
            handleGetRequest();
        } else if (method.equals("HEAD")) {
            handleHeadRequest();
        } else if (method.equals("POST")) {
            handlePostRequest();
        } else if (method.equals("PUT")) {
            handlePutRequest();
        } else if (method.equals("OPTIONS")) {
            handleOptionsRequest();
        } else if (method.equals("DELETE")) {
            handleDeleteRequest();
        } else if (method.equals("TRACE")) {
            handleTraceRequest();
        } else if (method.equals("CONNECT")) {
            handleConnectRequest();
        } else {
            throw new HTTPException(HTTP.NOT_IMPLEMENTED);
        }
    }

    /** Handles an HTTP GET request from the client.*/
    private void handleGetRequest() throws HTTPException {
        describeFile();
        try {
            response.finishHeaders();
            FileInputStream file = new FileInputStream(requestFile);
            /* Read and send file in blocks.*/
            byte[] fileData = new byte[READ_BLOCK];
            for (int i=0; i<requestFile.length(); i+=READ_BLOCK) {
                int bytesRead = file.read(fileData);
                response.rawOut.write(fileData, 0, bytesRead);
            }
            file.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Handles an HTTP HEAD request from the client.*/
    private void handleHeadRequest() throws HTTPException {
        describeFile();
        try {
            response.finishHeaders();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Handles an HTTP POST request from the client. Not
      * implemented yet.
      */
    private void handlePostRequest() throws HTTPException {
        throw new HTTPException(HTTP.NOT_IMPLEMENTED);
    }

    /** Handles an HTTP PUT request from the client. Not
      * implemented yet.
      */
    private void handlePutRequest() throws HTTPException {
        throw new HTTPException(HTTP.NOT_IMPLEMENTED);
    }

    /** Handles an HTTP OPTIONS request from the client. Not
      * implemented yet.
      */
    private void handleOptionsRequest() throws HTTPException {
        throw new HTTPException(HTTP.NOT_IMPLEMENTED);
    }

    /** Handles an HTTP DELETE request from the client. Not
      * implemented yet.
      */
    private void handleDeleteRequest() throws HTTPException {
        throw new HTTPException(HTTP.NOT_IMPLEMENTED);
    }

    /** Handles an HTTP TRACE request from the client.*/
    private void handleTraceRequest() throws HTTPException {
        try {
            sendStatus(HTTP.OK);
            sendBasicHeaders();
            response.sendHeader("Content-Type: message/http");
            response.finishHeaders();
            // echo the client's request back to them
            response.out.write(request.getRawRequest());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Handles an HTTP CONNECT request from the client. Not
      * implemented yet.
      */
    private void handleConnectRequest() throws HTTPException {
        throw new HTTPException(HTTP.NOT_IMPLEMENTED);
    }

    /** Sends the headers about the URI the client asked for. This method
      * does the "legwork" when dealing with files: it takes the URI from
      * the client, uses {@link #translateURI(String)} to get a
      * <code>File</code>, checks for errors, and then sends the
      * relevant headers to the client about the specified URI. It is
      * used by both the HTTP GET and HEAD methods.
      */
    private void describeFile() throws HTTPException {
        requestFile = translateURI(request.getURI());

        if (requestFile.exists() == false)
            throw new HTTPException(HTTP.NOT_FOUND);

        if (requestFile.canRead() == false)
            throw new HTTPException(HTTP.FORBIDDEN);

        try {
            sendStatus(HTTP.OK);
            sendBasicHeaders();
            response.sendHeader("Content-Length: " + requestFile.length());
            response.sendHeader("Last-Modified: " + HTTP.formatDate(
                                        new Date(requestFile.lastModified())));
            response.sendHeader("Content-Type: " +
                Tornado.mime.getContentType(requestFile));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Concludes the work with the client and informs the ServerPool.*/
    private void finishConnection() {
        if (response != null) {
            try {
                response.finishResponse();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        serverPool.decrementBusyThreads();
    }

    /** Sends the specified HTTP error code page to the client.*/
    private void sendErrorPage(HTTPException httpE) {
        try {
            sendStatus(httpE.getCode());
            sendBasicHeaders();
            response.sendHeader("Content-Type: text/html");
            response.finishHeaders();
            response.out.write(httpE.getErrorPage());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** Sends the specified HTTP status code to the client. This is just
      * a simple wrapper over {@link tornado.Response#sendStatus(int)},
      * with one additional function: it notes the status code in the access
      * log before sending it.
      */
    private void sendStatus(int statusCode) throws IOException {
        accessLog.setStatusCode(statusCode);
        response.sendStatus(statusCode);
    }

    /** Sends the HTTP headers to the client that are always sent. These
      * headers are those used in common by all HTTP responses.
      */
    private void sendBasicHeaders() throws IOException {
        response.sendHeader("Date: " + HTTP.formatDate(new Date()));
        response.sendHeader("Server: " + Tornado.config.getVersionSig());
        response.sendHeader("Connection: close");
    }

    /** Translates the URI to a filename. This takes an <b>absolute</b>
      * URI, performs some security checks, and translates this URI into
      * the designated file on the local filesystem. It then returns this
      * file.
      */
    private File translateURI(String uri) throws HTTPException {
        String relURI = uri.substring(uri.indexOf('/', 7));
        if (uri.indexOf("..", 1) != -1) {
            throw new HTTPException(HTTP.NOT_FOUND);
        }
        return new File(Tornado.config.getDocumentRoot() + relURI);
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -