Tomcat-- introduce common sense and manually implement tomcat1

1. HTTP protocol

1.1 Features

1. Supports client / server model.
2. simple and fast: a customer service request to the server, instead of sending the request method and path. Request method commonly used GET, HEAD, POST. Each method provides a different type of client contacts the server. Due to the simple HTTP protocol, HTTP server makes the program a small scale, so the communication is very fast.
3. Flexible: HTTP allows the transmission of any type of data object. It is the type of transmission being marked by Content-Type.
4. No connection: Meaning No limitation is attached only one request per connection. After the server processes client requests and receives the customer's response, i.e., disconnected. In this way it can save transmission time.
5. stateless: HTTP protocol is stateless protocol. No state is no protocol for transaction processing and memory. If the lack of state means that the subsequent processing required in front of the information, it must be retransmitted, which may result in the amount of data transmitted for each connection is increased. On the other hand, when it does not require previous information in response to a faster server.

1.2 requesting section

 http request consists of three parts, namely: a request line, a request header, the request body

1.2.1 request line

The method begins with a request line symbol, separated by spaces, URI, and the protocol version followed by a request in the following format: Method Request-URI HTTP-Version CRLF  

1. Method represents a request method;

2. Request-URI is a uniform resource identifier;

3. HTTP-Version represents the HTTP protocol version of the request;

4. represents a carriage return and line CRLF (CRLF as the end of the addition, it does not allow a separate character CR or LF).

For example: POST /index.html http / 1.1 (line feed)

1.2.2 request header

Allows the client request header is transmitted to the server requests additional information, and the client's own information.

Format: request header in the form of key-value pairs, separated by a blank line finally indicates the end of the request headers.

E.g:

k1:v1
k2:v2
k3:v3

username=xxx

Common request header
the Accept
the Accept request header field is used to specify what type of information the client accepted. eg: Accept: image / gif, indicates that the client wishes to receive resources GIF image format; Accept: text / html, indicates that the client wishes to accept html text.
The Charset-the Accept
the Accept the Charset request-header field is used to specify the character sets accepted by the client. eg: Accept-Charset:. iso -8859-1, gb2312 If this field is not set in the request message, the default character set can be any acceptable.
-Encoding the Accept
the Accept-Encoding request header field is similar to Accept, but it is acceptable for specifying content encoding. eg: Accept-Encoding:. gzip.deflate If the request is not set this field to the message server assumes that the client for encoding various contents are acceptable.
Language-the Accept
the Accept-Language request header field similar to Accept, but it is used to specify a natural language. eg: Accept-Language:. zh -cn If the request is not set in the message header field, the server assumes that the client can accept a variety of languages.
The Authorization
the Authorization request header field is mainly used to prove the client has permission to view a resource. When a browser to access a page, if the server receives a response code of 401 (unauthorized), you may send a request Authorization request header field contains, requires the server to be verified.
Host (transmission request, the header field is required)
Host request header field is mainly used to specify the Internet host and port number of the requested resource, it is usually extracted from the HTTP URL, eg:
We enter in your browser: http: //www.guet.edu.cn/index .html
request message sent by the browser, will contain Host request header field, as follows:
Host: www.guet.edu.cn
used herein default port number 80, if a port number is specified, then becomes: Host: www.guet.edu.cn: specify the port number
User-Agent
we landed Internet forums, you often will see some welcome message, which lists the name and version of your operating system, the name of the browser you are using and versions, which often makes a lot of people feel very magical, in fact, is to get the server application from the User-Agent header field to the request information. User-Agent request header field allows the client to its operating system, browser, and other attribute tells the server. However, the header field is not required, if you write a browser ourselves, do not use User-Agent request header field, then the server will not know our message.
Examples request header:
the GET /form.html the HTTP / 1.1 (CRLF)
the Accept: Image / GIF, Image / X-xbitmap, Image / JPEG, file application / X-Shockwave-Flash, file application / vnd.ms-Excel, file application / VND Powerpoint-.ms, the Application / msword, * / * (CRLF)
the Accept-Language: zh-CN (CRLF)
the Accept-Encoding: gzip, the deflate (CRLF)
If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)
If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF)
User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)
Host:www.guet.edu.cn (CRLF)
Connection:Keep-Alive (CRLF)
(CRLF)

1.2.3 Request Body

POST request body mode only. After the contents of the request is a request blank line head body, a carrier for carrying data to the service delivery the client-side

1.3 part of the response

 After receiving and interpreting a request message, the server returns a HTTP response message.

HTTP response is composed of three parts, namely: a status line, the message header, the response body

1.3.1 Status Line

Status line format is as follows: HTTP-Version Status-Code Reason-Phrase CRLF

HTTP-Version indicates the version of the HTTP protocol server;

Status-Code represents the server sends back a response status code;

Reason-Phrase represent text description of the status code.

1.3.2 message header

  HTTP request message from the client to the server and the server to the client in response to the composition. Request and response messages are a start line (request message, the request line is the starting line, a response message, a status line is the starting line), the message header (optional), a blank line (CRLF line only), the message body (optional) components.

HTTP message header includes common header, a request header, response header, the header entity.
Each header field is a name + ":" + space + value composition, the name of a message header fields are case insensitive.

1, general header
in an ordinary header, header field for a small number of all request and response messages, but not for the entity to be transmitted only for message transmission.
EG:
the Cache-Control command is used to specify a cache, the instruction cache is unidirectional (buffer command response will not necessarily appear in the request), and a separate instruction cache (not affect a message to another message handling caching mechanism), similar to the header field HTTP1.0 use of Pragma.
Cache instruction request includes: no-cache (for indicating a request or response message can not cache), no-store, max- age, max-stale, min-fresh, only-if-cached;
cache instruction response comprises : public, Private, cache-NO, NO-Store, the Transform-NO, the MUST-revalidate, Proxy-revalidate, maxage, S-maxage.
EG: to indicate the IE browser (client) do not cache pages, server-side JSP program can be written as follows: response.sehHeader ( "the Cache-Control", "Cache-NO");
//response.setHeader("Pragma","no-cache "); action corresponding to the above code, usually both / / combination of
this code will be provided in the common header field in the response message sent: Cache-Control: no-cache


Date common header field indicates the date and time of message generation

Connection ordinary header field allows the sending options specified connection. For example, a continuous connection is specified, or designated "close" option, notification server, when the response is completed, close the connection

2, request header
request header to allow the client to the server with the requested information additional information about itself and the client.
Common request header
the Accept
the Accept request header field is used to specify what type of information the client accepted. eg: Accept: image / gif, indicates that the client wishes to receive resources GIF image format; Accept: text / html, indicates that the client wishes to accept html text.
The Charset-the Accept
the Accept the Charset request-header field is used to specify the character sets accepted by the client. eg: Accept-Charset:. iso -8859-1, gb2312 If this field is not set in the request message, the default character set can be any acceptable.
-Encoding the Accept
the Accept-Encoding request header field is similar to Accept, but it is acceptable for specifying content encoding. eg: Accept-Encoding:. gzip.deflate If the request is not set this field to the message server assumes that the client for encoding various contents are acceptable.
Language-the Accept
the Accept-Language request header field similar to Accept, but it is used to specify a natural language. eg: Accept-Language:. zh -cn If the request is not set in the message header field, the server assumes that the client can accept a variety of languages.
The Authorization
the Authorization request header field is mainly used to prove the client has permission to view a resource. When a browser to access a page, if the server receives a response code of 401 (unauthorized), you may send a request Authorization request header field contains, requires the server to be verified.
Host (transmission request, the header field is required)
Host request header field is mainly used to specify the requested resource Internet host and port number, which is usually extracted from the HTTP URL, eg:
we enter in the browser: http://www.guet.edu.cn/index .html
request message sent by the browser, will contain Host request header field, as follows:
Host: www.guet.edu.cn
used herein default port number 80, if a port number is specified, then becomes: Host: www.guet.edu.cn : specify the port number
User-Agent
we landed Internet forums, you often will see some welcome message, which lists the name and version of your operating system, the name of the browser you are using and versions, which often makes a lot of people feel very magical, in fact, is to get the server application from the User-Agent header field to the request information. User-Agent request header field allows the client to its operating system, browser, and other attribute tells the server. However, the header field is not required, if you write a browser ourselves, do not use User-Agent request header field, then the server will not know our message.
Examples request header:
the GET /form.html the HTTP / 1.1 (CRLF)
the Accept: Image / GIF, Image / X-xbitmap, Image / JPEG, file application / X-Shockwave-Flash, file application / vnd.ms-Excel, file application / VND Powerpoint-.ms, the Application / msword, * / * (CRLF)
the Accept-Language: zh-CN (CRLF)
Accept-Encoding:gzip,deflate (CRLF)
If-Modified-Since:Wed,05 Jan 2007 11:21:25 GMT (CRLF)
If-None-Match:W/"80b1a4c018f3c41:8317" (CRLF)
User-Agent:Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0) (CRLF)
Host:www.guet.edu.cn (CRLF)
Connection:Keep-Alive (CRLF)
(CRLF)

3, response header
response headers can not allow the server to pass on the additional information in response to a status line, and information and information about the server to a resource identified by the Request-URI to access the next step.
Common response header
the Location
the Location response header field receiver for redirecting to a new location. Location response header field used to replace the domain name in time.
Server
Server response header field contains server software to process the information request. Header field is the User-Agent request corresponds. The following is
an example Server response header field:
Server: the Apache-Coyote / 1.1
the WWW-the Authenticate
the WWW-the Authenticate response header field must be included in 401 (unauthorized) response message, the client receives the 401 response message time, and Authorization header field when sending the request the server to be verified, the server response header contains the header fields.
eg: WWW-Authenticate: Basic realm = "! Basic Auth Test" // server can be seen on the requested resource uses basic authentication mechanism.


4, the entity header of
the request and a response message may be transmitted entity. An entity by the entity header field, and entity body composition, but does not mean that the entity header fields and entities to send the text to be together, you can send only entity header field. Entity headers defined on the entity body: meta-information resources (eg whether the entity body) and request identified.
Common entity header of
the Content-Encoding
the Content-Encoding entity header field is used as a media type modifiers, and a value indicating the coding has been applied to the entity body of the additional content, thus to obtain the referenced Content-Type header field media type, the corresponding decoding mechanism must be used. Content-Encoding compression method for recording such a document, EG: Content-Encoding: gzip
Content-Language
Content-Language entity header field describes the natural language resources used. This field is not set is considered an entity content will be available to all languages read
by. EG: the Content-Language: DA
the Content-the Length
the Content-entity the Length header field for indicating the length of the entity body of the decimal number is stored in bytes to represent.
The Type-the Content
the Content-term the Type header field indicates the entity to a recipient entity body of the media type. EG:
the Content-the Type: text / HTML; charset = the ISO-8859-1
the Content-the Type: text / HTML; charset = GB2312
Last-Modified
Last-Modified entity header field for the last modified date and time indication of resources.
The Expires
the Expires header field gives the entity date and time response expired. In order for a proxy server or browser updates the cache after a period of time (when accessing the page was visited again, loaded directly from the cache, faster response times and reduce server load) of the page, we can use Expires entity header fields specified page time expired. EG: the Expires: Thu, 15 Sep 2006 16:23:12 GMT
HTTP1.1 the client and the cache must be other illegal date format (including zero) considered to have expired. eg: In order for the browser not to cache pages, we can also use Expires entity header fields, set to 0, jsp program as follows: response.setDateHeader ( "Expires", " 0");

2. Socket Programming

2.1 analog Client

Data written for a client to obtain the server response

package cn.bjc.bs;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TestClient {
	/*
	 * 1. 建立一个Socket对象,连接网址与端口号
	 * 2. 获取输出流对象
	 * 3. 获取输入流对象
	 * 4. 将HTTP协议的请求部分发送到服务端
	 * 5. 读取来自服务端的数据打印到控制台
	 * 6. 释放资源
	 * */
	public static void main(String[] args) throws Exception {
		// 1. 建立一个Socket对象,连接网址与端口号
		Socket socket = new Socket("yun.itheima.com",80);
		// 2. 获取输出流对象
		InputStream in = socket.getInputStream();
		// 3. 获取输入流对象
		OutputStream out = socket.getOutputStream();
		// 4. 将HTTP协议的请求部分发送到服务端  
		// 4.1 请求资源  /open/c-4/p/1.html
		out.write("GET /open/c-4/p/1.html HTTP 1.1\n".getBytes());
		// 4.2 请求头
		out.write("HOST:yun.itheima.com\n".getBytes());
		// 4.3 空行
		out.write("\n".getBytes());
		
		// 5. 读取来自服务端的数据打印到控制台
		int i = in.read();
		while(i != -1){
			System.out.print((char)i);
			i = in.read();
		}
		
		// 6. 释放资源
		in.close();
		in = null;
		out.close();
		out=null;
	}
}

2.2 analog service ends

To write a piece of code, a request to the server in response to the analog browser

package cn.bjc.bs;

import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServer {

	public static void main(String[] args) throws Exception{
		ServerSocket serverSocket = null;
		Socket socket = null;
		OutputStream out = null;
		try {
			// 1. 创建ServerSocket对象,监听本机的8080端口
			serverSocket = new ServerSocket(8080);
			while(true){
				// 2. 等待来自客户端的请求获取和客户端对应的Socket对象
				socket = serverSocket.accept();
				// 3. 通过获取到的Socket对象获取到输出流
				out = socket.getOutputStream();
				// 4. 通过获取到的输出流对象将HTTP协议响应部分发送到客户端
				// 4.1 响应头
				out.write("HTTP/1.1 200 OK\n".getBytes());
				out.write("Content-Type:text/html;charset=utf-8\n".getBytes());
				out.write("Server:Apache-Coyote/1.1\n".getBytes());
				out.write("\n\n".getBytes());
				// 4. 响应体
				StringBuffer buffer = new StringBuffer();
				buffer.append("<html>");
				buffer.append("  <head><title>标题</title></head>");
				buffer.append("  <body>");
				buffer.append("       <h1>xxx</h1>");
				buffer.append("       <a href='http://www.baidu.com'>百度</a>");
				buffer.append("  </body>");
				buffer.append("</html>");
				out.write(buffer.toString().getBytes());
				out.flush();
			}
		} finally{
			// 5. 释放资源
			out.close();
			out = null;
			socket.close();
			socket = null;
		}
	}
}

In the browser enter: HTTP: // localhost: 8080 /

FIG Server Response:

3. Manually achieve TomCat

3.1 static resources

Case:

1. Publish static resources in webcontent demo1.html, demo2.html

2. Start Tomcat

3. When the client to the server to initiate a different request, localhost: 8080 / demo.html

4. The server can be the corresponding HTML page in response to the client.

3.1.1 Project Creation

Create a java project, as:

3.1.2 implement server-side preparations

1. Define the absolute path for storing static variables WEB.ROOT WebContent directory

2. Define a static variable url, store static resource request this service end of the name

E.g:

// 定义静态变量,用于存放服务端weContent目录的绝对路径
public static String WEB_ROOT = System.getProperty("user.dir")+File.separator+"webContent";
// 定义静态变量,用于存放本次请求的静态页面的名称
private static String url;

3.1.3 implement server startup code

1. Create a ServerSocket object, the machine listens on port 8080

2. waiting for a request from a client

public static void main(String[] args) throws Exception {
    ServerSocket server = null;
	Socket socket = null;
	// 1. 创建ServerSocket,监听本地8080端口,等待来自客户端的请求
	try {
		server = new ServerSocket(8080);
		while(true){
			// 获取客户端对应的socket
			socket = server.accept();
		}
	} catch (IOException e) {
		e.printStackTrace();
}

3.1.4 HTTP server to achieve the requested portion of the code

1. portion of the data read request HTTP protocol

2. Parse the request line, get this request static resource name

public static void main(String[] args) throws Exception {
	ServerSocket server = null;
	Socket socket = null;
	OutputStream out = null;
	InputStream in = null;
	// 1. 创建ServerSocket,监听本地8080端口,等待来自客户端的请求
	try {
		server = new ServerSocket(8080);
		while(true){
			// 获取客户端对应的socket
			socket = server.accept();
			// 获取输入流对象
			in = socket.getInputStream();
			// 获取输出流对象
			out = socket.getOutputStream();
			// 获取HTTP协议的请求部分,截取客户端要访问的资源名称,将这个资源名称赋值给url
			parse(in);
			// 发送静态资源
			sendStaticResource(out);
		}
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		
	}
}

3.1.5 implement HTTP protocol server sends a response to the client part

1. Read static resource to the server via the input stream memory

2. The transmission protocol HTTP response to the client portion

private static void sendStaticResource(OutputStream out) throws Exception {
		// 1. 定义一个字节数组,用于存放本次请求的静态资源demo01.html的内容
		byte[] bytes = new byte[2048];
		// 2. 定义一个文件输入流,用户获取静态资源demo01.html中的内容
		FileInputStream fis = null;
		try {
			// 3. 创建文件对象File,代表本次要请求的资源demo01.html
			File file = new File(WEB_ROOT,url);
			// 4. 如果文件存在
			if(file.exists()){
				// 4.1 向客户端输出HTTP协议的响应行/响应头
				out.write("HTTP/1.1 200 OK\n".getBytes());
				out.write("Server:apache-Coyote/1.1\n".getBytes());
				out.write("Content-Type:text/html;charset=utf-8\n".getBytes());
				out.write("\n".getBytes());
				// 4.2 获取到文件输入流对象
				fis = new FileInputStream(file);
				// 4.3 读取静态资源demo01.html中的内容到数组中
				int ch = fis.read(bytes);
				while(ch != -1){
					// 4.4 将读取到数组中的内容通过输出流发送到客户端
					out.write(bytes, 0, ch);
					ch = fis.read(bytes);
				}
			}else {
				// 5. 如果文件不存在
				// 5.1 向客户端响应文件不存在的消息
				out.write("HTTP/1.1 404 not found\n".getBytes());
				out.write("Server:apache-Coyote/1.1\n".getBytes());
				out.write("Content-Type:text/html;charset=utf-8\n".getBytes());
				out.write("\n".getBytes());
				String errMsg = "file not found";
				out.write(errMsg.getBytes());
			}
		} catch(Exception e){
			e.printStackTrace();
		}finally {
			// 6. 释放资源
			if(null != fis){
				fis.close();
			}
		}
		
	}

The complete code:

package cn.bjc.mytomcat.v1;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServer {

	// 定义静态变量,用于存放服务端weContent目录的绝对路径
	public static String WEB_ROOT = System.getProperty("user.dir")+File.separator+"webContent";
	// 定义静态变量,用于存放本次请求的静态页面的名称
	private static String url;
	public static void main(String[] args) throws Exception {
		ServerSocket server = null;
		Socket socket = null;
		OutputStream out = null;
		InputStream in = null;
		// 1. 创建ServerSocket,监听本地8080端口,等待来自客户端的请求
		try {
			server = new ServerSocket(8080);
			while(true){
				// 获取客户端对应的socket
				socket = server.accept();
				// 获取输入流对象
				in = socket.getInputStream();
				// 获取输出流对象
				out = socket.getOutputStream();
				// 获取HTTP协议的请求部分,截取客户端要访问的资源名称,将这个资源名称赋值给url
				parse(in);
				// 发送静态资源
				sendStaticResource(out);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			
		}
	}
	
	private static void sendStaticResource(OutputStream out) throws Exception {
		// 1. 定义一个字节数组,用于存放本次请求的静态资源demo01.html的内容
		byte[] bytes = new byte[2048];
		// 2. 定义一个文件输入流,用户获取静态资源demo01.html中的内容
		FileInputStream fis = null;
		try {
			// 3. 创建文件对象File,代表本次要请求的资源demo01.html
			File file = new File(WEB_ROOT,url);
			// 4. 如果文件存在
			if(file.exists()){
				// 4.1 向客户端输出HTTP协议的响应行/响应头
				out.write("HTTP/1.1 200 OK\n".getBytes());
				out.write("Server:apache-Coyote/1.1\n".getBytes());
				out.write("Content-Type:text/html;charset=utf-8\n".getBytes());
				out.write("\n".getBytes());
				// 4.2 获取到文件输入流对象
				fis = new FileInputStream(file);
				// 4.3 读取静态资源demo01.html中的内容到数组中
				int ch = fis.read(bytes);
				while(ch != -1){
					// 4.4 将读取到数组中的内容通过输出流发送到客户端
					out.write(bytes, 0, ch);
					ch = fis.read(bytes);
				}
			}else {
				// 5. 如果文件不存在
				// 5.1 向客户端响应文件不存在的消息
				out.write("HTTP/1.1 404 not found\n".getBytes());
				out.write("Server:apache-Coyote/1.1\n".getBytes());
				out.write("Content-Type:text/html;charset=utf-8\n".getBytes());
				out.write("\n".getBytes());
				String errMsg = "file not found";
				out.write(errMsg.getBytes());
			}
		} catch(Exception e){
			e.printStackTrace();
		}finally {
			// 6. 释放资源
			if(null != fis){
				fis.close();
			}
		}
		
	}
	private static void parse(InputStream in) throws Exception {
		// 1. 定义一个变量,存放HTTP协议请求部分数据
		StringBuffer content = new StringBuffer();
		// 2. 定义一个数组,存放HTTP协议请求部分数据
		byte[] buffer = new byte[2048];
		// 3. 定义一个变量i,代表读取数据到数组中之后,数据量的大小
		int i = -1;
		// 4. 读取客户端发过来的数据,将数据读取到字节数组buffer中,i代表读取数据量的大小311字节
		i = in.read(buffer);
		// 5. 遍历字节数组,将数组中的数据追加到content变量中
		for(int j = 0 ; j < i ; j++){
			content.append((char)buffer[j]);
		}
		// 6. 打印HTTP协议请求部分数据
		System.out.println(content);
		// 7. 截取客户端要请求的资源路径 demo.html,赋值给url
		parseUrl(content.toString());
		System.out.println(url);
	}

	// 解析请求数据得到请求连接
	private static void parseUrl(String content) {
		/*
		 * 	GET /erp/dep/getAll HTTP/1.1
			Host: localhost:8080
			Connection: keep-alive
			Upgrade-Insecure-Requests: 1
			User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
			Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng;q=0.8
			Accept-Encoding: gzip, deflate, br
			Accept-Language: zh-CN,zh;q=0.9
			Cookie: __guid=111872281.1743065663273879000.1567260921404.8972
		 * 
		 * */
		// 1. 截取客户端请求资源的名称   /erp/dep/getAll
		// 2. 定义2个变量,存放请求行的2个空格位置
		int index1,index2;
		// 3. 获取http请求行的第一个空格的位置
		index1 = content.indexOf(" ");
		if(index1 != -1){ // 表示存在第一个空格
			// 从第一个空格之后开始查找
			// 4. 获取http请求行的第二个空格的位置
			index2 = content.indexOf(" ", index1+1);
			if(index2 > index1){
				// 5. 截取字符串获取到本次请求的资源的名称
				url = content.substring(index1+2, index2);
			}
		}
	}

}

running result:

In the browser enter: HTTP: // localhost: 8080 / demo1.html

In the browser enter: HTTP: // localhost: 8080 / demo11.html

Published 128 original articles · won praise 6 · views 3234

Guess you like

Origin blog.csdn.net/weixin_43318134/article/details/103658349