preface

I recently read How Tomcat Works in Depth and found it easy to read, and every single one

Chapter 1 explains the principle of Tomcat step by step. In the following chapters, Tomcat is improved based on the new functions in chapter 1.

The result is a simplified version of Tomcat. So if you are interested, please read it in order. This article is to record the knowledge points of chapter 1

And source code implementation (make wheels).

Copy the code

How to implement

HTTP protocol is our Web server and browser interaction protocol, the specific knowledge and background of this article will not be too tired to describe. A simple example would be:

  • Enter http://www.baidu.com in your browser and press Enter.
  • The browser probably sent the following HTTP request to Baidu’s server:
GET/index. HTTP / 1.1 HTML

Host: www.baidu.com

.

Copy the code
  • When baidu Web server receives our request, it finds the corresponding server resources and accordingly:
HTTP / 1.1 200 OK

.



<html>

<head>

<title>Google it and you'll see</title>

</head>

<body>

.

</body>

</html>

Copy the code

The static (HTML/images/CSS, etc.)web server implementation is also relatively simple:

Code implementation

Use Java heresocketThe API implements a simple static Web server.

Copy the code
  • Create a new main method with the following core pseudocode:
// Enable socket Server 8080 port listening.

ServerSocket server = new ServerSocket(8080.1, InetAddress.getByName("127.0.0.1"));



try (Socket accept = serverSocket.accept();

InputStream inputStream = accept.getInputStream();

OutputStream outputStream = accept.getOutputStream()) {

// Parse the user's request

Request request = new Request();

request.setRequestStream(inputStream);

request.parseRequest();

// Generate a response object and respond to a static resource

Response resp = new Response(outputStream, request);

resp.accessStaticResources();

} catch (IOException e) {

LOGGER.warn("catch from user request.",e);

}

// Shut down the server

serverSocket.close();

Copy the code
  • The Request object

    Main function: the user request (socketInputStream) parses to a string, extracting the URI in the request

    Copy the code

Parse the string as follows:

StringBuilder requestStr = new StringBuilder();

int i;

// New a byte buffer array

byte[] buffer = ArrayUtil.generatorCache();

try {

i = inputStream.read(buffer);

} catch (IOException e) {

e.printStackTrace();

i = -1;

}

// Convert read byte to String

for (int j = 0; j < i; j++) {

requestStr.append((char) buffer[j]);

}

// Parse the request string to extract the request URI

this.parseURI(requestStr.toString());

Copy the code

Now that the requested information is parsed into a string, how do we know what static resource it wants to request?

Let’s print the parse string:

    System.out.println(requestStr.toString());

Copy the code

GET /index.html HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive cache-control: max-age=0 user-agent: Mozilla / 5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36 upgrade-insecure -Requests: 1 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh; Q = 0.9

You can obviously see that the area in bold is the URI we want to extract, so how do we extract it? /index. HTML has a space before and after the string. IndexOf (String indexOf);

// Get the space index before /index.html

int oneSpace = requestStr.indexOf("");

// Get the space index after /index.html

int twoSpace = requestStr.indexOf("", oneSpace + 1);

// Intercepts the user request URI

uri = requestStr.substring(oneSpace + 1, twoSpace);

Copy the code
  • The Response object

    The above Request object has resolved the resource that the user wants to Request, so the function of Response is to find the file,

    Using Socket outputStream to output the file as a byte stream to the browser, we can display our HTML to the user

    Copy the code

    So where do we put our static files for this project? Take a look at our project structure:

    -main  

- Java Java code

-resources

-webroot the folder where our static resources are stored

Copy the code

Since we only use MAVEN to build the project and we do not use Spring or other frameworks, how do we locate the webroot folder? Refer to the code on the Internet:

String WEB_PROJECT_ROOT = HttpServer.class.getClassLoader().getResource("webroot").getFile().substring(1);

Copy the code

The previous doubts are solved, next we will directly find the corresponding file to write back to the end of the ~ pseudo-code is as follows:

// Find the requested resource file according to the request URI

File staticResource = new File(HttpServer.WEB_PROJECT_ROOT + request.getUri());

// The resource exists

if (staticResource.exists() && staticResource.isFile()) {

outputStream.write(this.responseToByte(200."OK"));

write(staticResource);

// The resource does not exist. Use the default 404

} else {

staticResource = new File(HttpServer.WEB_PROJECT_ROOT + "/404.html");

outputStream.write(this.responseToByte(404."file not found"));

write(staticResource);

}

Copy the code

The responseToByte() method is only responsible for printing the response line:

HTTP / 1.1 200 OK

Copy the code

If the resource does not exist, we print:

    HTTP/1.1 404 file not found

Copy the code

The write() method is also simple, turning an incoming file object into a stream and using the socket’s outputStream output

try (FileInputStream fis = new FileInputStream(file)) {

byte[] cache = new byte[1024];

int read;

while ((read = fis.read(cache, 0.1024)) != -1) {

outputStream.write(cache, 0, read);

}

}

Copy the code

See the effect

Run the main method, open our browser and output 127.0.0.1/index.html, press Enter, you can see the result as shown:



Try entering a resource that does not exist:



Press F12 to see what the Http request and response look like:

Request:

GET/ABC. HTTP / 1.1 HTML

Host: 127.0.0.1:8080

Other headers ignore...



Response:

HTTP/1.1 404 file not found



<! DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>404 not found! </title>

</head>

<body>

<h1> Request page does not exist! </h1>

</body>

</html>

Copy the code

By now, Tomcat 1.0 web server has been developed. It can implement simple HTML, CSS, images and other resources access functions. In the next chapter, we will implement the following simple Servlet container function development:

Implement Tomcat part 2 with me: Implement a simple Servlet container

PS: The source of this chapter has been uploaded to Github SimpleTomcat