您的位置:首页 > 其它

ServerSocket实现 一个简单的Web服务器 [引]

2017-12-08 17:12 741 查看
深入剖析tomcat ch01

项目代码

https://github.com/dzetJavaEE/tomcat_ch01

项目结构



请求结果



打印信息

============== HTTP服务器 运行中...... ==================
GET /index.html HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

======= 发送至浏览器[客户端] 的静态资源 :
D:\___JavaEE\tomcat_ch01\webroot\index.html
GET /images/logo.gif HTTP/1.1
Accept: image/png, image/svg+xml, image/jxr, image/*;q=0.8, */*;q=0.5
Referer: http://localhost:8080/index.html Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive

======= 发送至浏览器[客户端] 的静态资源 :
D:\___JavaEE\tomcat_ch01\webroot\images\logo.gif


HttpServer

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;

/**
* Http服务器
*/
public class HttpServer {

/**
WEB_ROOT is the directory where our HTML and other files reside.
For this package, WEB_ROOT is the "webroot" directory under the working directory.
The working directory is the location in the file system from where the java command was invoked.
*/
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot";

// 关机 命令
private static final String SHUTDOWN_COMMAND = "/SHUNTDOWN";

// 收到的关机命令
private boolean shutdown = false;

/**
* 主方法
* @param args
*/
public static void main(String[] args) {
HttpServer server = new HttpServer();
server.await();
}

/**
* 等待
*/
public void await() {
System.out.println("============== HTTP服务器 运行中...... ==================");

ServerSocket serverSocket = null;
int port = 8080; // 端口
int backlog = 1; // 请求传入连接队列的最大长度。
String host = "127.0.0.1"; // 服务器ip
try {
// 1 创建一个ServerSocket实例,然后进入一个while循环
serverSocket = new ServerSocket(port,backlog, InetAddress.getByName(host));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}

// 循环等待一个请求
while (!shutdown){
Socket socket = null;
InputStream input = null;
OutputStream output = null;

try {
// 2 当从8080端口接收到HTTP请求后,ServerSocket类的accept()方法返回,等待结束
socket = serverSocket.accept();
// 2.1 从accept()方法返回的Socket实例中获取InputStream对象 和 OutputStream对象
input = socket.getInputStream();
output = socket.getOutputStream();

// 3 创建一个Request对象,并调用其parse()方法来解析HTTP请求的原始数据
// 创建请求对象和解析
Request request = new Request(input);
request.parse();

// 4 创建一个Response对象,并分别调用其setRequest()方法和sendStaticResource()方法
// 创建响应对象
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();

// 5 关闭套接字
// 关闭套接字
socket.close();

// 5.1 调用Request类的getUri()方法来测试HTTP请求的URI是否是关机命令
// 检查上一个URI是否是关机命令
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);

} catch (Exception e) {
e.printStackTrace();
}
}
}

}


Request

import java.io.IOException;
import java.io.InputStream;

/**
* HTTP请求
*/
public class Request {
private InputStream input;
private String uri;

public Request(InputStream input) {
this.input = input;
}

/**
* 解析HTTP请求中的原始数据
* 调用私有方法parseUri() 来解析HTTP请求的URI
*/
public void parse() {
// Read a set of characters from the socket
StringBuffer requestStringBuffer = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];

try {
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
requestStringBuffer.append((char) buffer[j]);
}
String requestString = requestStringBuffer.toString();
System.out.println(requestString);
uri = parseUri(requestString);
}

/**
* 解析HTTP请求的URI,并存储至变量uri
* @param requestString
* @return
*/
private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1){
index2 = requestString.indexOf(' ', index1+1);
if (index2 > index1){
return requestString.substring(index1 +1, index2);
}
}
return null;
}

/**
* 返回HTTP请求的URI
* @return
*/
public String getUri() {
return uri;
}
}


Response

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

/*
HTTP Response = Status-Line
*(( general-header | response-header | entity-header ) CRLF)
CRLF
[ message-body ]
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
*/

/**
* HTTP响应
*/
public class Response {
/**
* 私有静态常量int BUFFER_SIZE
*/
private static final int BUFFER_SIZE = 1024;

/**
* HTTP请求
*/
Request request;

/**
* 输出
*/
OutputStream output;

public Response(OutputStream output) {
this.output = output;
}

/**
* 设置HTTP请求
*
* @param request
*/
public void setRequest(Request request) {
this.request = request;
}

/**
* 发送静态资源
*
* @throws IOException
*/
public void sendStaticResource() throws IOException {
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;

try {
File file = new File(HttpServer.WEB_ROOT, request.getUri());
System.out.println("======= 发送至浏览器[客户端] 的静态资源 :\n" + file.getPath());

// 文件存在
if (file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while (ch != -1) {
output.write(bytes, 0, ch);
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
}
// 文件未找到
else {
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) {
System.out.println(e.toString());
e.printStackTrace();
} finally {
if (fis != null) {
fis.close();
}
}
}

//    public void setRequest(Request request) {
//
//    }
}


index.html

<html>
<head>
<title>Welcome to BrainySoftware</title>
</head>
<body>
<img src="./images/logo.gif">
<br>
Welcome to BrainySoftware.
</body>
</html>


logo.gif



end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: