tomcat系列(一)--一个简单的web服务器

本系列帖子是假定读者已经可以初步使用tomcat的基础之上写的。如果你还不会使用tomcat,那么推荐学习韩顺平老师的《细说servlet》视频教程。

参考书籍:深入剖析tomcat

本帖主要是搭建一个简单的web服务器

程序结构如下图所示:

这里写图片描述

HttpServer类的代码:

package com.tomcat.http;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class HttpServer {

    /**
     * System.getProperty("user.dir")的结果是:D:\develop\tomcat 获取项目所在路径
     * System.out.println(File.separator);的结果是 \
     */
    public static final String WEB_ROOT = 
            System.getProperty("user.dir")+File.separator+"webroot";

    public static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; 

    //the shutdown command received
    private boolean shutdown = false; //关闭服务器的状态标志

    public static void main(String[] args) {
        HttpServer server = new HttpServer();//创建对象
        server.await();//调用方法
    }
    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            //创建serverSocket对象
            serverSocket对象 = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (Exception 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();
                //创建Request对象,并解析请求头
                Request request = new Request(input);
                request.parse();

                //创建Response对象
                Response response = new Response(output);
                response.setRequest(request);
                response.setStaticResource();

                //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;
            }
        }
    }

}

Request类的代码如下:

package com.tomcat.http;

import java.io.InputStream;

public class Request {
    private InputStream input;
    private String uri;

    public Request(InputStream input) {

        this.input = input;
    }

    /**
     * 用于解析HTTP请求中的原始数据
     * 
     * 如何工作:需要知道请求头和请求体的结构
     */
    public void parse() {
        //read a set of characters from the socket
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);

        } catch (Exception e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char)buffer[j]);
        }
        System.out.println(request.toString());
        uri = psrseUri(request.toString());
    }

    /**
     * 解析HTTP请求的URI
     * @param requestString
     * @return
     */
    private String psrseUri(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;
    }
}

Response类的代码:

package com.tomcat.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

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 setStaticResource() {
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis = null;
        try {
            System.out.println(123);
            File file = new File(HttpServer.WEB_ROOT,request.getUri());
            if(file.exists()) {
                fis = new FileInputStream(file);
                int ch;
                while(((ch = fis.read(bytes, 0, BUFFER_SIZE) )!= -1)) {
                    output.write(bytes, 0, ch);
                }
            }else {
                //file not found
                String errorMessage = "file not found";
                output.write(errorMessage.getBytes());
            }

        } catch (Exception e) {
            System.out.println(e.toString());
        }finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

}

index.html的代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    hello world.
</body>
</html>

如何发起请求:在浏览器输入如下地址:http://localhost:8080/index.html

最终结果:

页面返回:hello world.

控制台打印输出结果:

GET /index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Idea-82847fdb=bc822efc-9482-4d70-af1b-9810633d90f9; Idea-deaf1dd9=75405b31-277a-4999-a725-48667070d583

总结:本文旨在说明一个web服务器的基本工作原理。

猜你喜欢

转载自blog.csdn.net/guo20082200/article/details/80531634