Java 多线程Web服务器的设计与实现

 java
 

目的:

  • 熟悉简单网络的搭建与基本配置;
  • 熟悉socket、多线程编程;
  • 熟悉JDK编程工具的基本使用;
  • 熟悉HTTP协议;
  • 熟悉Web服务器的基本工作原理和配置。

整体框架图
手写版框架图
项目结构图
项目结构
具体代码:
主线程MultiThreadWebServer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package ***自己的包名***;
import java.net.* ;
public final class MultiThreadWebServer {
public static void main(String argv[]) throws Exception {

ServerSocket socket = new ServerSocket(9999);
while (true) {
// Listen for a TCP connection request.
Socket connection = socket.accept();
HttpRequest request = new HttpRequest(connection);
Thread thread = new Thread(request);
thread.start();
// socket.close();
}
}
}

处理请求线程HttpRequest.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
package ***自己的包名***;
import java.io.* ;
import java.net.* ;
import java.util.* ;

final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;

public HttpRequest(Socket socket) throws Exception {
this.socket=socket; }

public void run() {
try {processRequest();}
catch (Exception e) {System.out.println(e);}
}

private void processRequest() throws Exception {
InputStreamReader is=new InputStreamReader(socket.getInputStream());
DataOutputStream os=new DataOutputStream(socket.getOutputStream());
BufferedReader br = new BufferedReader(is);

//读取第一行
String requestLine;
requestLine=br.readLine();
System.out.println(requestLine);

//读取剩余行
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine); }


StringTokenizer tokens = new StringTokenizer(requestLine);//将第一行以空格为准拆分
tokens.nextToken(); //第一次为第一个
String fileName = tokens.nextToken();//第二次为第二个为“/文件名”
fileName="."+fileName;//在前面加一个“.”与"/"合起来为“./”表示当前目录文件

FileInputStream fis = null ;
boolean fileExists = true ;

try {fis = new FileInputStream(fileName);}
catch (FileNotFoundException e) {fileExists = false ;}

// Reponse
String statusLine = null; //状态行
String contentTypeLine = null; //Content-Type行
String entityBody = null; //Entity body部分
if (fileExists) {
statusLine="HTTP/1.1 200 OK"+CRLF;
contentTypeLine = "Content-type: " + contentType( fileName ) + CRLF;
}
else {
statusLine="HTTP/1.1 200 NotFound"+CRLF;
contentTypeLine = "Content-type: text/html"+CRLF;
entityBody ="<html><title>Not found</title><h1>404 NotFound</h1></html>";
}

os.writeBytes(statusLine);
os.writeBytes(contentTypeLine);
os.writeBytes(CRLF);
if (fileExists) { sendBytes(fis, os);
fis.close(); }
else { os.writeBytes(entityBody); }

os.close();
br.close();
socket.close();
}
//发送字节
private static void sendBytes(FileInputStream fis,OutputStream os) throws Exception {
byte[] buffer = new byte[1024];
int bytes=0;
while((bytes=fis.read(buffer))!=-1){
os.write(buffer,0,bytes);//将数组从偏移量0开始的bytes个字节写入直至写完
}
}

private static String contentType(String fileName) {

if(fileName.endsWith(".htm") || fileName.endsWith(".html")|| fileName.endsWith(".txt")) {
return "text/html";
}
if(fileName.endsWith(".jpg")) {
return "image/jpeg";
}
if(fileName.endsWith(".gif")) {
return "image/gif";
}
if(fileName.endsWith(".png")) {
return "image/png";
}
return "application/octet-stream";
}
}
本地运行结果:
![404][3]
![txt][4]
![index][5]
![jpg][6]
![控制台输出][7]


将java项目打包为jar文件,放到服务器。
cd到jar文件所在目录
执行以下语句,即可在服务器执行该Java 程序:
java -jar 文件名.jar
例如我的文件为demo.jar如下执行
java -jar demo.jar

至此全部完成!!!恭喜你!!