-
Notifications
You must be signed in to change notification settings - Fork 0
/
BootstrapV1.java
144 lines (125 loc) · 4.9 KB
/
BootstrapV1.java
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package com.studying.concurrency.v1;
import com.studying.concurrency.util.Logs;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by junweizhang on 17/11/20.
* 第一版 WebServer,只实现基本功能,所有处理都是main线程中.
*/
public class BootstrapV1 {
private ServerSocket ss;
private File docRoot;
private boolean isStop = false;
public BootstrapV1(int port, File docRoot) throws Exception {
// 1. 服务端启动8080端口,并一直监听;
this.ss = new ServerSocket(port, 10);
this.docRoot = docRoot;
}
public void serve() {
Logs.SERVER.info("Http Server ready to receive requests...");
while (!isStop) {
try {
process();
} catch (Exception e) {
Logs.SERVER.info("serve error", e);
isStop = true;
// System.exit(1);
}
}
}
/**
* 接收客户端的Socket,解析输入字节流,并返回结果.
* @throws Exception
*/
private void process() throws Exception {
// 2. 监听到有客户端(比如浏览器)要请求http://localhost:8080/,那么建议连接,TCP三次握手;
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
/**
* 3. 建立连接后,读取此次连接客户端传来的内容(其实就是解析网络字节流并按HTTP协议去解析);
* GET /dir1/dir2/file.html HTTP/1.1
*/
String requestLine = reader.readLine();
Logs.SERVER.info("requestLine is : {}", requestLine);
if (requestLine == null || requestLine.length() < 1) {
Logs.SERVER.error("could not read request");
return;
}
String[] tokens = requestLine.split(" ");
String method = tokens[0];
String fileName = tokens[1];
File requestedFile = docRoot;
String[] paths = fileName.split("/");
for (String path : paths) {
requestedFile = new File(requestedFile, path);
}
if (requestedFile.exists() && requestedFile.isDirectory()) {
requestedFile = new File(requestedFile, "index.html");
}
BufferedOutputStream bos = new BufferedOutputStream(os);
// 4. 解析到请求路径(比如此处是根路径),那么去根路径下找资源(比如此处是index.html文件);
if (requestedFile.exists()) {
Logs.SERVER.info("return 200 ok");
long length = requestedFile.length();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(requestedFile));
String contentType = URLConnection.guessContentTypeFromStream(bis);
byte[] headerBytes = createHeaderBytes("HTTP/1.1 200 OK", length, contentType);
bos.write(headerBytes);
// 5. 找到资源后,再通过网络流将内容输出,当然,还是按照HTTP协议去输出,这样客户端(浏览器)就能正常渲染、显示网页内容;
byte[] buf = new byte[2000];
int blockLen;
while ((blockLen = bis.read(buf)) != -1) {
bos.write(buf, 0, blockLen);
}
bis.close();
} else {
Logs.SERVER.info("return 404 not found");
byte[] headerBytes = createHeaderBytes("HTTP/1.0 404 Not Found", -1, null);
bos.write(headerBytes);
}
bos.flush();
socket.close();
}
/**
* 生成HTTP Response头.
*
* @param content
* @param length
* @param contentType
* @return
*/
private byte[] createHeaderBytes(String content, long length, String contentType) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(baos));
bw.write(content + "\r\n");
if (length > 0) {
bw.write("Content-Length: " + length + "\r\n");
}
if (contentType != null) {
bw.write("Content-Type: " + contentType + "\r\n");
}
bw.write("\r\n");
bw.flush();
byte[] data = baos.toByteArray();
bw.close();
return data;
}
public static void main(String[] args) {
try {
int port = 8080;
String docRootStr = "htmldir";
URL url = BootstrapV1.class.getClassLoader().getResource(docRootStr);
File docRoot = new File(url.toURI());
BootstrapV1 bootstrap = new BootstrapV1(port, docRoot);
bootstrap.serve();
} catch (Exception e) {
Logs.SERVER.error("main start error", e);
System.exit(1);
}
}
}