Tomcat-3 A Simple Web Server

Excerpted from <How Tomcat works>

A web application server must stand by all time as it does not know when a client application will try to connection to it. in order for your application to be able to stan by all the time, you need to use the java.net.ServerSocket class.

To create a server socket, you need to specify the IP address and port number the server will be listening on. Another important property of a server socket is tis bakclog, which is the miximum queue length of incomming connection request before the server socket starts to refuse the imcoming requests.

This web server application consists of three classes:HttpServer.java, Request.java, Response.java. The entry point of this application(the main method) can be found in the HttpServer class. The main method create an instance of HttpServer and calls its await method. The await method, as the name implies, wait for HTTP requests on a designated port, processes them, and sends response back to the clients. It keeps waiting until a shutdown command is received. This application cannot do more than sending static resources, such as HTML files and image files, residing in a certain directory. It also displays the incoming HTTP request byte streams on the console. However, it does not send any header, such as dates or cookies to the browser.

All the three classes are reprented in the following:

package ex01.pyrmont;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.File;
import static java.lang.System.out;
public class HttpServer {
    /**
     * WEB_ROOT is the directory where our HTML and other files reside. * For
     * this package, WEB_ROOT is the "webroot" directory under the * working
     * directory. * The working directory is the location in the file system *
     * from where the java command was invoked.
     */
    public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";

    // shutdown command
    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";

    // the shutdown command received
    private boolean shutdown = false;
    public static void main(String[] args) {
        out.println("User's dir:/t"+System.getProperty("user.dir"));
        HttpServer server = new HttpServer();
        server.await();
    }
    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        // Loop waiting for a request
        while (!shutdown) {
            Socket socket = null;
            InputStream input = null;
            OutputStream output = null;
            try {
                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();

                // create Request object and parse
                Request request = new Request(input);
                request.parse();

                // create Response object
                Response response = new Response(output);
                response.setRequest(request);
                response.sendStaticResource();

                // Close the socket
                socket.close();

                // check if the previous URI is a shutdown command
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
}

The web server can serve static resources found in the directory indicated by the public static final WEB_ROOT and all subdirectory under it.

After running main method on this class, to request for a static resource, you type the following URL in your brower's Address or URL box:

Http://machineName:port/staticResource

For instance, if you want to ask the HttpServer object to send the index.html file, you use the following URL:

http://localhost:8080/index.html

Certainly, index.html must reside in WEB_ROOB directory.

package ex01.pyrmont;
import java.io.IOException;
import java.io.InputStream;
public class Request {
    private InputStream input;
    private String uri;
    public Request(InputStream input) {
        this.input = input;
    }
    public void parse() {
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        System.out.print("Parse:/t"+request.toString());
        uri = parseUri(request.toString());
    }
    private String parseUri(String requestString) {
        int index1, index2;
        index1 = requestString.indexOf(' ');
        if (index1 != -1) {
            index2 = requestString.indexOf(' ', index1 + 1);
            if (index2 > index1)
                return requestString.substring(index1 + 1, index2);
        }
        return null;
    }
    public String getUri() {
        return uri;
    }
}

This class represents and HTTP request. An instance of this class is constructed by passing the InputStream object obtained from a Socket that handles the communication with the client. you call one of the read methods of the InputStream object to obtain the HTTP request raw data.

The Request class is offered below. Request class has two public methods, parse and getUri. The parse method parses the raw data in the HTTP request. Not much is done by this method. The only information it makes available is the URI of the HTTP request that it obtains by calling the private method parseUri. The parseUri method stores the URI in the variable. the public getUri method is invoked to return the URI of the HTTP request.

package ex01.pyrmont;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
/* HTTP Response = Status-Line *(( general-header | response-header | entity-header ) CRLF) CRLF [ message-body ] Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
public class Response {
    private static final int BUFFER_SIZE = 1024;
    Request request;
    OutputStream output;
    public Response(OutputStream output) {
        this.output = output;
    }
    public void setRequest(Request request) {
        this.request = request;
    }
    public void sendStaticResource() throws IOException {
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis = null;
        try {
            File file = new File(HttpServer.WEB_ROOT, request.getUri());
            if (file.exists()) {
                fis = new FileInputStream(file);
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                while (ch != -1) {
                    output.write(bytes, 0, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
            } else {
                String errorMessage = "HTTP/1.1 404 File Not Found/r/n" + "Content-Type: text/html/r/n" + "Content-Length: 23/r/n" + "/r/n"
                        + "<h1>File Not Found</h1>";
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            if (fis != null)
                fis.close();
        }
    }
}

The Response class has two public methods: setRequest and sendStaticResource. The setRequest method is used to pass a Request object to the Response object. The sendStaticResource method is used to send a static resource, such as an HTML file.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值