The content is the key points of the first chapter of "In-depth Analysis of Tomcat" and my own summary. If there is any unclear description, you can check the original book.
1. HTTP protocol:
1. Definition: A protocol used for communication between servers and clients, allowing web servers and browsers to send and receive data over the Internet. It is a request and response protocol that uses the reliable TCP protocol. The TCP protocol's port is 80 and is a connection-oriented protocol.
2. Three components of HTTP protocol request: These three parts are separated by carriage return and line feed (CRLF)
Request part: Method (7 types including GET/POST, others are rarely used and are introduced in the book) [space, this part of the content is separated by spaces] Uniform Resource Identifier URI [space, this part of the content is separated by spaces] ] Protocol/Protocol Version
URLs are usually relative to the root directory of the server, so they start with "/".
Request header: The request header contains useful information about the client environment and the body content of the request. For example, it may include the language of the browser settings, the length of the main content, etc. Each header is separated by a carriage return line feed (CRLF) character.
Request body content: For the HTTP request format, it is very important to have a carriage return line feed (CRLF) between the header and the body content. CRLF tells the HTTP server where the body content begins. In some Internet programming books, CRLF is also considered the fourth part of HTTP requests.
3. The HTTP response also includes three parts:
· Method—Uniform Resource Identifier (URI)—Protocol/Version
· Response header
2. Communication between server and client
1. Communication between the server and the client requires two parts: Socket (client) and ServerSocket (server)
(1) ServerSocket (java.net.ServerSocket, server-side socket), to create a server socket, you need to use one of the four construction methods provided by the ServerSocket class. You need to specify the IP address and port number that the server socket will listen on. Typically, the IP address will be 127.0.0.1, which means that the server socket will be listening on the local machine. The IP address that the server socket is listening on is called the bind address. Another important attribute of the server socket is the backlog, which is the maximum queue length of incoming connection requests before the server socket starts rejecting incoming requests. The four construction methods are:
ServerSocket ss = new ServerSocket();//Create an unbound ServerSocket
ServerSocket ss = new ServerSocket(int port);//Create a ServerSocket bound to a certain port
ServerSocket ss = new ServerSocket(int port, int log);//Create a ServerSocket bound to a certain port and set the maximum queue length.
ServerSocket ss = new ServerSocket(int port, int log, InetAddress address);//Create a ServerSocket bound to a certain address and a certain port, and set the maximum queue length.
For the fourth constructor, the binding address must be an instance of InetAddress. A simple way to construct an InetAddress object is to call its static method getByName, passing in a string containing the host name, like the following code Same.
InetAddress.getByName("127.0.0.1");
Common methods to create ServerSocket:
new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
The code constructs a ServletSocket that listens to port 8080 of the local machine, and its queue length is 1.
After the server is created, it remains in a waiting state (TCP protocol, a reliable transmission protocol, is a synchronous protocol, that is, it will wait until no response is returned)
(2) Socket (java.net.Socket class, client socket): You need to know the IP/host name and port number of the server you want to access, and then you can send a request to the server. You can use one of the many construction methods of Socket to create a Socket
new Socket ("yahoo.com", 80);
Once you have successfully created an instance of the Socket class, you can use it to send and receive byte streams. To send a byte stream, you must first call the getOutputStream method of the Socket class to obtain a java.io.OutputStream object. To send text to a remote application, you often construct a java.io.PrintWriter object from the returned OutputStream object. To receive a byte stream from the other end of the connection, you can call the getInputStream method of the Socket class to return a java.io.InputStream object.
(3) The server receives the client’s connection request through the accept() method, establishes a connection with the client, and returns a Socket
Socket s = ss. accept();
(4) An input stream and an output stream can be obtained through Socket. The input stream is used to read the client request data, and the output stream is used to return response information to the client.
For example: InputStream input = s.getInputStream();
OutputStream output = s.getOutputStream();
3. Simple Web server communication example (it is recommended to copy it to MyEclipse to view and execute)
1. Server class
package com.socket.httpservertest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
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)
{
HttpServer server = new HttpServer();
server.await();
}
public void await() {
// System.out.println(System.getProperty("user.dir"));
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);
}
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;
}
}
}
}
package com.socket.httpservertest;
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() {
// 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); //将从输入流取2048长度的内容存到buffer字节数组中,如果内容不到2048,数组其他空间剩余空着
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j=0; j<i; j++)
{
request.append((char) buffer[j]);
}
System.out.print(request.toString());
uri = parseUri(request.toString());
}
private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
/*
* http请求行的结构:方法 统一资源标识符(URI) 协议/版本(它们之间以空格分隔)
* 例如:POST //examples/default.jsp HTTP/1.1
*/
if (index1 != -1) {// index1 == -1表示没找到
index2 = requestString.indexOf(' ', index1 + 1);//从index+1位置开始寻找‘ ’
if (index2 > index1)
return requestString.substring(index1 + 1, index2);
}
return null;
}
public String getUri()
{
return uri;
}
}
3. Response class
package com.socket.httpservertest;
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 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) { //ch==-1表示读到末尾了
output.write(bytes, 0, ch); //写出到浏览器
ch = fis.read(bytes, 0, BUFFER_SIZE);//再读会接上一次读的位置往下读,如果读到末尾就会返回-1,终止输出
}
} else {
// file not found
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) {
// thrown if cannot instantiate a File object
System.out.println(e.toString() );
} finally {
if (fis!=null)
fis.close();
}
}
}
4. Sample code function description: The browser inputs an http request, such as http://localhost:8080/MyHtml.html; after receiving the request, the server uses the input stream to read the request content to obtain the file location, and then uses the file input stream to read the file. content; finally return a response to the browser client and display the content in the html file on the browser, as shown in the figure:
5. Sample code cross-functional flow chart:
The above is the detailed content of Tomcat study notes (1) A simple web server. For more information, please follow other related articles on the PHP Chinese website!