前提

知识点

  • Socket
  • IO流

思路

  • 启动Socket服务,循环接收浏览器请求
  • 接收到请求后,取出流中数据
  • 判断目标资源是否存在,不存在则返回404,存在则通过输出流将目标资源响应给客户端

  • Server:开启Socket服务
  • Request:封装请求,处理相关的请求业务
  • Response:封装响应,处理相关的响应业务
  • Test:测试类

编码

1
2
3
4
GitHub https://github.com/pepsi-wyl/Web_Tomcat

git@github.com:pepsi-wyl/Web_Tomcat.git
https://github.com/pepsi-wyl/Web_Tomcat.git

HttpServer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import lombok.SneakyThrows;

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

/**
* @author by pepsi-wyl
* @date 2022-12-06 17:21
*/

// Socket服务
public class MyHttpServer {

// 端口号
private final int port = 8080;

// 接收请求
@SneakyThrows
public void receiving() {

// 创建Socket服务
ServerSocket serverSocket = new ServerSocket(port);

// 循环接收请求
while (true) {
// 获取连接对象
Socket socket = serverSocket.accept();
// 获取连接对象的输入流和输出流
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();

// 创建Request
MyHttpRequest request = new MyHttpRequest(inputStream);
// 在Request中解析输入流对象,获取目标资源信息
String uri = request.parse();

// 创建Response
MyHttpResponse response = new MyHttpResponse(outputStream);
// 在Response中
response.sendRedirect(uri);
}
}
}

HttpRequest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import lombok.SneakyThrows;

import java.io.InputStream;

/**
* @author by pepsi-wyl
* @date 2022-12-06 19:04
*/

// 处理请求对象
public class MyHttpRequest {

// 输入流
private final InputStream inputStream;

// 构造方法
public MyHttpRequest(InputStream inputStream) {
this.inputStream = inputStream;
}

// 解析输入流中的信息
@SneakyThrows
public String parse() {
// 将输入流中的数据存到数组中
byte[] bytes = new byte[1024];
inputStream.read(bytes);

// 解析获得目标资源信息并且返回
return getUri(new String(bytes));
}

// 根据请求获取目标资源信息
private String getUri(String request) {
// 获取资源下标
int index1 = request.indexOf(' ');
int index2 = request.indexOf(' ', index1 + 1);
// 返回资源
return request.substring(index1 + 1, index2);
}
}

HttpResponse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import lombok.SneakyThrows;

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

/**
* @author by pepsi-wyl
* @date 2022-12-06 21:30
*/

// 处理响应对象
public class MyHttpResponse {

// 输入流
private final OutputStream outputStream;

// 构造方法
public MyHttpResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}

// 响应
@SneakyThrows
public void sendRedirect(String uri) {

// 获取资源保存路径
String path = System.getProperty("user.dir") + "/src" + "/main" + "/resources" + "/web";
// 获取资源文件
File file = new File(path + uri);

// 处理返回对象
if (!file.exists()) { // 不存在 则返回不存在 404
// 要返回信息
String error = "404 File Not Found!";
// 返回
this.outputStream.write(getResponseMessage("404", error).getBytes());
} else { // 存在 则返回目标资源 200
// 读取资源文件
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[(int) file.length()];
fileInputStream.read(bytes);
// 返回信息
String result = new String(bytes);
// 返回
this.outputStream.write(getResponseMessage("200", result).getBytes());
}
}

// 封装响应信息
public String getResponseMessage(String code, String message) {
return "HTTP/1.1 " + code
+ "\r\n"
+ "Content-type: " + "text/html"
+ "\r\n"
+ "Content-Length: " + message.length()
+ "\r\n"
+ "\r\n"
+ message;
}
}

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author by pepsi-wyl
* @date 2022-12-06 17:33
*/

// 测试方法
// http://localhost:8080/index.html
public class Test {
public static void main(String[] args) {
System.out.println("Server startup successfully......");
// 创建服务对象
MyHttpServer server = new MyHttpServer();
// 启动服务接收请求
server.receiving();
}
}

index.html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>

index

</body>
</html>

测试

启动

访问存在的资源

1
http://localhost:8080/index.html

访问不存在的资源

1
http://localhost:8080/t.html